1

OpenGL のさまざまなタイプの GLSL シェーダーに頭を悩ませようとしています。現時点では、2D レイヤード タイルの実装に苦労しています。何らかの理由で、シェーダーに渡される int 値は常に 0 (または null の可能性が高い) です。

現在、20x20 のタイルで構成される 2048x2048px の 2D テクスチャがあります。1 つのクワッドをテクスチャリングし、頂点シェーダーに渡す int のブロックに基づいてタイルのインデックスを変更しようとしています。

クワッドの位置にフロートの vec2 を渡しています (実際には TRIANGLE_STRIP)。また、タイルの 6 層を表す 6 つの int を渡そうとしています。

私の入力:

// Build and compile our shader program
Shader ourShader("b_vertex.vertexShader", "b_fragment.fragmentShader");

const int floatsPerPosition = 2;
const int intsPerTriangle = 6;
const int numVertices = 4;
const int sizeOfPositions = sizeof(float) * numVertices * floatsPerPosition;
const int sizeOfColors = sizeof(int) * numVertices * intsPerTriangle;
const int numIndices = 4;
const int sizeOfIndices = sizeof(int) * numIndices;

float positions[numVertices][floatsPerPosition] =
{
    { -1, 1 },
    { -1, -1 },
    { 1, 1 },
    { 1, -1 },
};

// ints indicating Tile Index
int colors[numVertices][intsPerTriangle] =
{
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
    { 1, 2, 3, 4, 5, 6 },
};

// Indexes on CPU
int indices[numVertices] =
{
    0, 1, 2, 3,
}; 

私のセットアップ:

GLuint vao, vbo1, vbo2, ebo; // Identifiers of OpenGL objects

glGenVertexArrays(1, &vao); // Create new VAO
                            // Binded VAO will store connections between VBOs and attributes
glBindVertexArray(vao);

glGenBuffers(1, &vbo1); // Create new VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo1); // Bind vbo1 as current vertex buffer
                                     // initialize vertex buffer, allocate memory, fill it with data
glBufferData(GL_ARRAY_BUFFER, sizeOfPositions, positions, GL_STATIC_DRAW);
// indicate that current VBO should be used with vertex attribute with index 0
glEnableVertexAttribArray(0);
// indicate how vertex attribute 0 should interpret data in connected VBO
glVertexAttribPointer(0, floatsPerPosition, GL_FLOAT, GL_FALSE, 0, 0);

glGenBuffers(1, &vbo2); // Create new VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo2); // Bind vbo2 as current vertex buffer
                                     // initialize vertex buffer, allocate memory, fill it with data
glBufferData(GL_ARRAY_BUFFER, sizeOfColors, colors, GL_STATIC_DRAW);
// indicate that current VBO should be used with vertex attribute with index 1
glEnableVertexAttribArray(1);
// indicate how vertex attribute 1 should interpret data in connected VBO
glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0);

// Create new buffer that will be used to store indices
glGenBuffers(1, &ebo);
// Bind index buffer to corresponding target
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
// ititialize index buffer, allocate memory, fill it with data
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfIndices, indices, GL_STATIC_DRAW);

// reset bindings for VAO, VBO and EBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);



// Load and create a texture 
GLuint texture1 = loadBMP_custom("uvtemplate3.bmp");

GLuint texture2 = loadBMP_custom("texture1.bmp");

私の引き分け:

// Game loop
while (!glfwWindowShouldClose(window))
{
    // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
    glfwPollEvents();

    // Render
    // Clear the colorbuffer
    glClearColor(1.f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // Activate shader
    ourShader.Use();

    // Bind Textures using texture units
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);

    //add some cool params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    float borderColor[] = { 0.45f, 0.25f, 0.25f, 0.25f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);
    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1);

    // Draw container
    //glBindVertexArray(VAO);
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(vao);
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glDrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_INT, NULL);

    glBindVertexArray(0);

    // Swap the screen buffers
    glfwSwapBuffers(window);
}

vertexShader 内から値をハードコーディングすることで出力を調整できるため、私のシェーダーは確実に機能します。私の疑いは、値を正しく/正しい形式で渡していないか、頂点ごとに int[6] を含める必要があることをどこかに示していないことです。

int Base[6]; のレイアウト (場所 = 1) から何も読み取れません。考えられることはほぼすべて試しました。各intを個別に宣言し、2つのivec3、uint、および他に考えられるものを読み取ろうとしましたが、すべてが0で返されます。

完全を期すために、以下は私の頂点とフラグメント シェーダーです。

#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in int Base[6];

out vec2 TexCoord;
out vec2 TexCoord2;
out vec2 TexCoord3;
out vec2 TexCoord4;
out vec2 TexCoord5;
out vec2 TexCoord6;

//  0.5f,  0.5f,// 0.0f,   118.0f, 0.0f, 0.0f,   0.0f, 0.0f, // Top Right
//  0.5f, -0.5f,// 0.0f,   118.0f, 1.0f, 0.0f,   0.0f,0.009765625f, // Bottom Right
//  -0.5f, -0.5f,// 0.0f,   118.0f, 0.0f, 1.0f,   0.009765625f, 0.009765625f, // Bottom Left
//  -0.5f,  0.5f//, 0.0f,   118.0f, 1.0f, 0.0f,   0.009765625f, 0.0f  // Top Left 

void main()
{

int curBase = Base[5];

int curVertex = gl_VertexID % 4;
vec2 texCoord = (curVertex == 0?
vec2(0.0,0.0):(
curVertex == 1?
vec2(0.0,0.009765625):(
curVertex == 2?
vec2(0.009765625,0.0):(
curVertex == 3?
vec2(0.009765625,0.009765625):(
vec2(0.0,0.0)))))
);
gl_Position = vec4(position, 0.0f, 1.0f);

TexCoord = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
//curBase = Base+1;
TexCoord2 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
//curBase = Base+2;
TexCoord3 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f)
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f));
}

断片:

#version 330 core
//in vec3 ourColor;
in vec2 TexCoord;
in vec2 TexCoord2;
in vec2 TexCoord3;
in vec2 TexCoord4;
in vec2 TexCoord5;
in vec2 TexCoord6;

out vec4 color;

// Texture samplers
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;

void main()
{
color = (texture(ourTexture2, TexCoord )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord2 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord3 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord4 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord5 )== vec4(1.0,0.0,1.0,1.0)?
(texture(ourTexture2, TexCoord6 )== vec4(1.0,0.0,1.0,1.0)?
    vec4(0.0f,0.0f,0.0f,0.0f)
:texture(ourTexture2, TexCoord6 ))
:texture(ourTexture2, TexCoord5 ))
:texture(ourTexture2, TexCoord4 ))
:texture(ourTexture2, TexCoord3 ))
:texture(ourTexture2, TexCoord2 ))
:texture(ourTexture2, TexCoord ));
}
4

1 に答える 1

3

これは、次の 2 つの点で間違っています。

glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0);

GL の頂点属性は、2 ~ 4 個のコンポーネントのスカラーまたはベクトルにすることができます。したがって、 のsizeパラメーターはglVertexAttribPointer1、2、3、または 4 の値を取ることができます。別の値 ( intsPerTriangle == 6) を使用すると、呼び出しがエラーを生成するだけでGL_INVALID_VALUE何の効果もないため、ポインターを設定しません。

頂点ごとに 6 つの値を渡したい場合は、6 つの異なるスケーラー属性を使用する (6 つの属性スロットを消費する) か、2 つの 3d ベクトル (2 つのスロットのみを消費する) のようないくつかのベクトルにこれをパックすることができます。選択したパッキングに関係なく、使用中の各属性スロットに対して適切な属性ポインターを設定する必要があります。

ただし、glVertexAttribPointerユースケースには間違った機能でもあります。これは浮動小数点属性を定義しており、シェーダーでfloat/として一致する宣言が必要です。vec*入力できるGL_INTということは、GPU がその場で浮動小数点への変換を実行できるということです。

intor ivec(または対応する符号なし) 属性を使用する場合は、属性を設定するときに (その関数名のIglVertexAttribIPointerに注意してください) を使用する必要があります。

于 2016-07-04T20:29:26.673 に答える