2013-06-20 79 views
4

我有一個GLfloats數組,當我繪製四邊形時我用作位置和顏色(所以每個頂點有4個浮點數)。我想添加爲我的四邊形着色的能力,並且認爲我會將RGBA打包到單個GLuint中,然後將它們與位置一起發送到GPU。我可以在OpenGL(C++)的緩衝區中混合使用數據類型嗎?

那麼,我可以以某種方式發送4個GLfloats,然後1個GLuint到GPU?

下面是相關代碼:

void SpriteRenderer::Init() 
{ 
    vertexBufferArrayInserts = 0; 

    hasBegun = GL_FALSE; 

    glGenBuffers(1, &vertexBuffer); 
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAX_VERTEX_BUFFER_SIZE, 0, GL_STREAM_DRAW); 

    glGenBuffers(1, &elementBuffer); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * MAX_ELEMENT_BUFFER_SIZE, 0, GL_STREAM_DRAW); 

    ////////////////////////////////////////////////////////////////////////// 
    //LOAD SHADER, CREATE AND USE PROGRAM 
    ////////////////////////////////////////////////////////////////////////// 
    glGenVertexArrays(1, &vertexArrayObject); 
    glBindVertexArray(vertexArrayObject); 

    vertexShaderID = LoadShaderFromFile("Shader", GL_VERTEX_SHADER); 
    fragmentShaderID = LoadShaderFromFile("Shader", GL_FRAGMENT_SHADER); 

    shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShaderID); 
    glAttachShader(shaderProgram, fragmentShaderID); 

    glBindFragDataLocation(shaderProgram, 0, "outColor"); 

    glLinkProgram(shaderProgram); 
    glUseProgram(shaderProgram); 

    shaderPosAttrib = glGetAttribLocation(shaderProgram, "position"); 
    glVertexAttribPointer(shaderPosAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0); 
    glEnableVertexAttribArray(shaderPosAttrib); 

    shaderTexCoordAttrib = glGetAttribLocation(shaderProgram, "texCoord"); 
    glVertexAttribPointer(shaderTexCoordAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 2)); 
    glEnableVertexAttribArray(shaderTexCoordAttrib); 

    shaderColorAttrib = glGetAttribLocation(shaderProgram, "Color"); 
    glVertexAttribPointer(shaderColorAttrib, 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); 
    glEnableVertexAttribArray(shaderColorAttrib); 

    shaderProjMatAttrib = glGetUniformLocation(shaderProgram, "projMat"); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 
} 

void SpriteRenderer::Draw(Vector2<GLfloat> position, Rect clipRect) 
{ 
    //TOP LEFT 
    vertexBufferArray[vertexBufferArrayInserts * 16] = position.X; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 1] = position.Y; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 2] = clipRect.GetLeftX()/512.0f; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 3] = clipRect.GetTopY()/512.0f; 
    colorBufferArray[vertexBufferArrayInserts * 4] = PackColor(255, 255, 255, 255); 

    //TOP RIGHT 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 4] = position.X + clipRect.GetWidth(); 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 5] = position.Y; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 6] = clipRect.GetRightX()/512.0f; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 7] = clipRect.GetTopY()/512.0f; 
    colorBufferArray[vertexBufferArrayInserts * 4 + 1] = PackColor(255, 255, 255, 255); 

    //BOTTOM RIGHT 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 8] = position.X + clipRect.GetWidth(); 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 9] = position.Y + clipRect.GetHeight(); 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 10] = clipRect.GetRightX()/512.0f; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 11] = clipRect.GetBottomY()/512.0f; 
    colorBufferArray[vertexBufferArrayInserts * 4 + 2] = PackColor(255, 255, 255, 255); 

    //BOTTOM LEFT 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 12] = position.X; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 13] = position.Y + clipRect.GetHeight(); 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 14] = clipRect.GetLeftX()/512.0f; 
    vertexBufferArray[vertexBufferArrayInserts * 16 + 15] = clipRect.GetBottomY()/512.0f; 
    colorBufferArray[vertexBufferArrayInserts * 4 + 3] = PackColor(255, 255, 255, 255); 

    //ELEMENT BUFFER 
    elementBufferArray[vertexBufferArrayInserts * 6] = vertexBufferArrayInserts * 4; 
    elementBufferArray[vertexBufferArrayInserts * 6 + 1] = vertexBufferArrayInserts * 4 + 1; 
    elementBufferArray[vertexBufferArrayInserts * 6 + 2] = vertexBufferArrayInserts * 4 + 2; 
    elementBufferArray[vertexBufferArrayInserts * 6 + 3] = vertexBufferArrayInserts * 4 + 2; 
    elementBufferArray[vertexBufferArrayInserts * 6 + 4] = vertexBufferArrayInserts * 4 + 3; 
    elementBufferArray[vertexBufferArrayInserts * 6 + 5] = vertexBufferArrayInserts * 4; 

    vertexBufferArrayInserts++; 

    if(vertexBufferArrayInserts == MAX_BUFFER_INSERTS) 
     Draw(); 
} 

void SpriteRenderer::Draw() 
{ 
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * vertexBufferArrayInserts * 16, vertexBufferArray); 
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertexBufferArrayInserts * 16, sizeof(GLuint) * vertexBufferArrayInserts * 4, colorBufferArray); 
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLint) * vertexBufferArrayInserts * 6, elementBufferArray); 

    glDrawElements(GL_TRIANGLES, vertexBufferArrayInserts * 6, GL_UNSIGNED_INT, 0); 

    vertexBufferArrayInserts = 0; 
} 

GLuint SpriteRenderer::PackColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a) { 
    GLint returnVal = (r << 24) + (g << 16) + (b << 8) + a; 

    return returnVal; 
} 
+3

他有他的問題做的代碼。他啓用顏色屬性數組,然後使用'glVertexAttribPointer'來指定數據的位置。然後,這些數據將在其頂點着色器中可用。你卡在哪裏? –

+0

我更新了原始問題 – Semicolon

+0

查看您嘗試的其他代碼(包括着色器)可能會有幫助。例如,你在調用'glVertexAttribPointer'之前是否綁定了緩衝區?你是否正確填充緩衝區?另外,根據你對'glVertexAttribPointer'的調用,我假設你將你的數組構造爲{float,float,float,float,int,float float,float,float,int,...}。但是當使用'glBufferSubData'時,你只修改了數組的最後五分之一?你可能想先嚐試使用2個獨立的緩衝區(這可能是你首先想要的)。 –

回答

3

你的問題在於:

glVertexAttribPointer(shaderColorAttrib, 1, GL_UNSIGNED_INT, 
    GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); 

這將解壓爲單個組件。

告訴您發送4個1字節組件GPU(這加起來是一個單一的32位值):

glVertexAttribPointer(shaderColorAttrib, 4, GL_UNSIGNED_BYTE, 
    GL_TRUE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 4)); 

請注意,我的歸一化標誌設置爲true。如果你發送此爲vec4的着色器,使每個組件轉換成你可能希望它在[0,1]範圍內做到這一點。

此外,而不是與sizeof(float)做很容易出錯的數學,考慮使一個結構和使用該結構的大小和offsetof生成你的步伐和頂點偏移:

struct vertex { 
    float4 position; 
    ubyte4 color; 
}; 

glVertexAttribPointer(shaderColorAttrib, 4, GL_FLOAT, 
    GL_FALSE, sizeof(vertex), offsetof(vertex, position)); 
glVertexAttribPointer(shaderColorAttrib, 4, GL_UNSIGNED_BYTE, 
    GL_TRUE, sizeof(vertex), offsetof(vertex, color)); 

一旦你開始混合數據類型,這種方式變得更加關鍵。只需注意struct padding;使用offsetof將確保工作正常,但您不希望浪費您的緩衝區對象空間。

+0

我注意到的另一件事是調用'glBindBuffer(GL_ARRAY_BUFFER,0);',然後調用'glBufferSubData'而不再綁定緩衝區。這不是問題嗎?我對OpenGL有點新鮮,所以我只是爲了自己的理解而提出這樣的問題:P –

+0

是的,我將緩衝區解除綁定,但是在嘗試將數據放入之前將其綁定。 我會如何將數據發送到GPU?我可以使用一個'glBufferSubData'嗎? – Semicolon

+0

這是大代碼轉儲的問題。大量的紅鯡魚,不完整的代碼路徑,老實說,我不會像泰勒顯然那樣密切關注它。 :) –

相關問題