void CKLBOGLWrapper::draw( GLenum mode, CShaderInstance* instance, CBuffer** ppBuffer, u32 bufferCount, CIndexBuffer* pIndexBuffer, CTextureUsage** array_pTexture, s32* uniformID, s32 indexCount) { // Force buffer to commit changes if they are VBO and were not updated. u32 n=0; while (n < bufferCount) { CBuffer* pBuffer = ppBuffer[n]; n++; if (pBuffer->VBOModified) { pBuffer->commitVBO(); } } if (pIndexBuffer->VBOModified) { pIndexBuffer->commitVBO(); } if (m_lastShaderInstance != instance) { // Same Shader with different param is also a possibility. if (!m_lastShaderInstance || (m_lastShaderInstance->m_pShaderSet != instance->m_pShaderSet)) { // Use Shader only when program really changes. dglUseProgram(instance->m_pShaderSet->programObj); } // Transform matrix // u32 _projectionUniform = dglGetUniformLocation(instance->m_pShaderSet->programObj, "Projection"); // dglUniformMatrix4fv(_projectionUniform, 1, 0, displayMatrix2D); m_lastShaderInstance = instance; } u32 _projectionUniform = dglGetUniformLocation(instance->m_pShaderSet->programObj, "Projection"); dglUniformMatrix4fv(_projectionUniform, 1, 0, displayMatrix2D); // // Process all input for shaders. // CShader* pVertexS = instance->m_pShaderSet->vertexShader; s32 maxVertexInput = pVertexS->countStreamInfo; s32 count = 0; while (count < maxVertexInput) { CShaderInstance::SInternalParam* pParam = &instance->paramArrayVertexVertexShader[count]; if (pParam->isConstantifiedOrUniform) { dglDisableVertexAttribArray(count); // Constantified switch (pParam->dType & 0x0F) { case VEC1F: dglVertexAttrib1fv(count, (GLfloat*)pParam->values); break; case VEC2: dglVertexAttrib2fv(count, (GLfloat*)pParam->values); break; case VEC3: dglVertexAttrib3fv(count, (GLfloat*)pParam->values); break; case VEC4BYTE: case VEC4: dglVertexAttrib4fv(count, (GLfloat*)pParam->values); break; default: klb_assertAlways("Invalid Type for vertex attribute"); } } else { // // Search in buffer the source mapping the shader input. // s32 vertID = instance->paramArrayVertexVertexShader[count].vertexInfoID; u32 n=0; while (n < bufferCount) { CBuffer* pBuffer = ppBuffer[n]; n++; SVertexEntry* pEntries = pBuffer->structure; SVertexEntry* pEntriesEnd = &pEntries[pBuffer->dynCount + pBuffer->vboCount]; while ((pEntries->vertexInfoID != vertID) && (pEntries < pEntriesEnd)) { pEntries++; } if (pEntries < pEntriesEnd) { GLint size = GLint(pParam->dType & 0xF); GLenum type = GL_FLOAT; GLboolean normalized = GL_FALSE; if (size == VEC4BYTE) { size = 4; type = GL_UNSIGNED_BYTE; normalized = GL_TRUE; } if (pEntries->isVBO) { _glBindBuffer(pBuffer->vboID); dglEnableVertexAttribArray(count); dglVertexAttribPointer( count, size, type, normalized, (pBuffer->strideVBO * sizeof(float)), (const void*)((pEntries->offset + pBuffer->offsetDrawVBO) * sizeof(float))); } else { _glBindBuffer(0); dglEnableVertexAttribArray(count); dglVertexAttribPointer( count, size, type, normalized, (pBuffer->strideDyn * sizeof(float)), &(((float*)pBuffer->ptrBuffer)[pEntries->offset + pBuffer->offsetDrawDyn])); } // Break and go to next array. break; } } } count++; } // // Process uniform parameters. // count = 0; s32 countTexture = 0; s32* pLocation = instance->m_pShaderSet->locationArray; // Vertex + Pixel shader. for (s32 n=0; n < 2; n++) { CShaderInstance::SInternalParam* pParam; CShaderInstance::SInternalParam* maxVertexUniform; // // Vertex & Pixel Shader. (MUST BE SAME ORDER AS CreateShaderSet !!!) // if (n == 0) { pParam = instance->paramArrayUniformVertexShader; maxVertexUniform = &pParam[pVertexS->countUniform]; } else { pParam = instance->paramArrayUniformPixelShader; maxVertexUniform = &pParam[instance->m_pShaderSet->pixelShader->countUniform]; } while (pParam < maxVertexUniform) { s32 location = *pLocation++; switch (pParam->dType & 0x0F) { case VEC1I: dglUniform1iv(location, 1, (GLint*)(pParam->values)); break; case VEC1F: dglUniform1fv(location, 1, (GLfloat*)(pParam->values)); break; case VEC2: dglUniform2fv(location, 1, (GLfloat*)(pParam->values)); break; case VEC3: dglUniform3fv(location, 1, (GLfloat*)(pParam->values)); break; case VEC4: dglUniform4fv(location, 1, (GLfloat*)(pParam->values)); break; case MMAT2: dglUniformMatrix2fv(location, 1, GL_FALSE, (GLfloat*)(pParam->values)); break; case MMAT3: dglUniformMatrix3fv(location, 1, GL_FALSE, (GLfloat*)(pParam->values)); break; case MMAT4: dglUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)(pParam->values)); break; case TEX2D: if (pParam->pTexture == NULL) { // // Process texture // CTextureUsage** pTex = array_pTexture; if (pTex != null) { s32* pUniID = uniformID; while ((*pTex != null) && (pParam->vertexInfoID != *pUniID)) { pTex++; pUniID++; } if (*pTex != null) { // Assign texture to texture unit and apply parameters. CTextureUsage* pUsage = *pTex; pUsage->activate(countTexture); // Link active texture unit to uniform dglUniform1i(location, countTexture); countTexture++; } else { // klb_assertAlways("Texture attribute is not mapped to a valid texture"); } } else { klb_assertAlways("No texture information when shader use texture"); } } /*else { // Assign texture to texture unit and apply parameters. CTextureUsage* pUsage = pParam->pTexture; pUsage->activate(countTexture); // Link active texture unit to uniform dglUniform1i(location, countTexture); countTexture++; }*/ break; } pParam++; } } // // Handle Index Buffer & Draw call. // if (pIndexBuffer->isVBO) { if (lastElementArrayBuffer != pIndexBuffer->vboID) { lastElementArrayBuffer = pIndexBuffer->vboID; dglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexBuffer->vboID); } dglDrawElements(mode, indexCount, GL_UNSIGNED_SHORT, 0); } else { if (lastElementArrayBuffer != 0) { lastElementArrayBuffer = 0; dglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } dglDrawElements(mode, indexCount, GL_UNSIGNED_SHORT, &pIndexBuffer->ptrBuffer[pIndexBuffer->offsetDraw]); } }