From 3b0e6ae65f651cd79f2ac070fc521f6de7fd734d Mon Sep 17 00:00:00 2001 From: coco24 <1281299809@qq.com> Date: Tue, 12 Mar 2024 11:00:22 +0800 Subject: [PATCH] Implement functional `rlNormal3f` --- src/rlgl.h | 202 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 184 insertions(+), 18 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index c34c3e5d8..0c4ac8e06 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -349,6 +349,7 @@ typedef struct rlVertexBuffer { float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *normals; // Vertex normal (XYZ - 3 components per vertex) (shader-location = 2) unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) unsigned int *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) @@ -357,7 +358,7 @@ typedef struct rlVertexBuffer { unsigned short *indices; // Vertex indices (in case vertex data comes indexed) (6 indices per quad) #endif unsigned int vaoId; // OpenGL Vertex Array Object id - unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data) + unsigned int vboId[5]; // OpenGL Vertex Buffer Objects id (5 types of vertex data) } rlVertexBuffer; // Draw call type @@ -1104,8 +1105,15 @@ static const char *rlGetCompressedFormatName(int format); // Get compressed form static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture) // Auxiliar matrix math functions +typedef struct rl_float16 { + float v[16]; +} rl_float16; +static rl_float16 rlMatrixToFloatV(Matrix mat); // Get float array of matrix data +#define rlMatrixToFloat(mat) (rlMatrixToFloatV(mat).v) // Get float vector for Matrix static Matrix rlMatrixIdentity(void); // Get identity matrix static Matrix rlMatrixMultiply(Matrix left, Matrix right); // Multiply two matrices +static Matrix rlMatrixTranspose(Matrix mat); // Transposes provided matrix +static Matrix rlMatrixInvert(Matrix mat); // Invert provided matrix //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations @@ -1468,7 +1476,10 @@ void rlVertex3f(float x, float y, float z) RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter] = RLGL.State.texcoordx; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].texcoords[2*RLGL.State.vertexCounter + 1] = RLGL.State.texcoordy; - // WARNING: By default rlVertexBuffer struct does not store normals + // Add current normal + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter] = RLGL.State.normalx; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 1] = RLGL.State.normaly; + RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].normals[3*RLGL.State.vertexCounter + 2] = RLGL.State.normalz; // Add current color RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.State.vertexCounter] = RLGL.State.colorr; @@ -1504,9 +1515,26 @@ void rlTexCoord2f(float x, float y) // NOTE: Normals limited to TRIANGLES only? void rlNormal3f(float x, float y, float z) { - RLGL.State.normalx = x; - RLGL.State.normaly = y; - RLGL.State.normalz = z; + float normalx = x; + float normaly = y; + float normalz = z; + if (RLGL.State.transformRequired) + { + normalx = RLGL.State.transform.m0*x + RLGL.State.transform.m4*y + RLGL.State.transform.m8*z; + normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z; + normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z; + } + float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz); + if (length != 0.0f) + { + float ilength = 1.0f / length; + normalx *= ilength; + normaly *= ilength; + normalz *= ilength; + } + RLGL.State.normalx = normalx; + RLGL.State.normaly = normaly; + RLGL.State.normalz = normalz; } // Define one vertex (color) @@ -2175,7 +2203,10 @@ void rlglInit(int width, int height) RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; // Init default vertex arrays buffers + // Simulate that the default shader has the location RL_SHADER_LOC_VERTEX_NORMAL to bind the normal buffer for the default render batch + RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL; RLGL.defaultBatch = rlLoadRenderBatch(RL_DEFAULT_BATCH_BUFFERS, RL_DEFAULT_BATCH_BUFFER_ELEMENTS); + RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL] = -1; RLGL.currentBatch = &RLGL.defaultBatch; // Init stack matrices (emulating OpenGL 1.1) @@ -2620,6 +2651,7 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad + batch.vertexBuffer[i].normals = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad batch.vertexBuffer[i].colors = (unsigned char *)RL_MALLOC(bufferElements*4*4*sizeof(unsigned char)); // 4 float by color, 4 colors by quad #if defined(GRAPHICS_API_OPENGL_33) batch.vertexBuffer[i].indices = (unsigned int *)RL_MALLOC(bufferElements*6*sizeof(unsigned int)); // 6 int by quad (indices) @@ -2630,6 +2662,7 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].vertices[j] = 0.0f; for (int j = 0; j < (2*4*bufferElements); j++) batch.vertexBuffer[i].texcoords[j] = 0.0f; + for (int j = 0; j < (3*4*bufferElements); j++) batch.vertexBuffer[i].normals[j] = 0.0f; for (int j = 0; j < (4*4*bufferElements); j++) batch.vertexBuffer[i].colors[j] = 0; int k = 0; @@ -2679,16 +2712,23 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements) glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); - // Vertex color buffer (shader-location = 3) + // Vertex normal buffer (shader-location = 2) glGenBuffers(1, &batch.vertexBuffer[i].vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[2]); + glBufferData(GL_ARRAY_BUFFER, bufferElements*3*4*sizeof(float), batch.vertexBuffer[i].normals, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + + // Vertex color buffer (shader-location = 3) + glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); + glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]); glBufferData(GL_ARRAY_BUFFER, bufferElements*4*4*sizeof(unsigned char), batch.vertexBuffer[i].colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer - glGenBuffers(1, &batch.vertexBuffer[i].vboId[3]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[3]); + glGenBuffers(1, &batch.vertexBuffer[i].vboId[4]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.vertexBuffer[i].vboId[4]); #if defined(GRAPHICS_API_OPENGL_33) glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferElements*6*sizeof(int), batch.vertexBuffer[i].indices, GL_STATIC_DRAW); #endif @@ -2755,6 +2795,7 @@ void rlUnloadRenderBatch(rlRenderBatch batch) glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[1]); glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[2]); glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[3]); + glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[4]); // Delete VAOs from GPU (VRAM) if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &batch.vertexBuffer[i].vaoId); @@ -2762,6 +2803,7 @@ void rlUnloadRenderBatch(rlRenderBatch batch) // Free vertex arrays memory from CPU (RAM) RL_FREE(batch.vertexBuffer[i].vertices); RL_FREE(batch.vertexBuffer[i].texcoords); + RL_FREE(batch.vertexBuffer[i].normals); RL_FREE(batch.vertexBuffer[i].colors); RL_FREE(batch.vertexBuffer[i].indices); } @@ -2796,8 +2838,13 @@ void rlDrawRenderBatch(rlRenderBatch *batch) glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer - // Colors buffer + // Normals buffer glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); + glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].normals); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].normals, GL_DYNAMIC_DRAW); // Update all buffer + + // Colors buffer + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); glBufferSubData(GL_ARRAY_BUFFER, 0, RLGL.State.vertexCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer @@ -2850,13 +2897,30 @@ void rlDrawRenderBatch(rlRenderBatch *batch) // Create modelview-projection matrix and upload to shader Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection); - float matMVPfloat[16] = { - matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3, - matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7, - matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11, - matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15 - }; - glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat); + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, rlMatrixToFloat(matMVP)); + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_PROJECTION], 1, false, rlMatrixToFloat(RLGL.State.projection)); + } + + // WARNING: For the following setup of the view, model, and normal matrices, it is expected that + // transformations and rendering occur between rlPushMatrix and rlPopMatrix. + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_VIEW], 1, false, rlMatrixToFloat(RLGL.State.modelview)); + } + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MODEL], 1, false, rlMatrixToFloat(RLGL.State.transform)); + } + + if (RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL] != -1) + { + glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_NORMAL], 1, false, rlMatrixToFloat(rlMatrixTranspose(rlMatrixInvert(RLGL.State.transform)))); + } if (RLGL.ExtSupported.vao) glBindVertexArray(batch->vertexBuffer[batch->currentBuffer].vaoId); else @@ -2871,12 +2935,17 @@ void rlDrawRenderBatch(rlRenderBatch *batch) glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01]); - // Bind vertex attrib: color (shader-location = 3) + // Bind vertex attrib: normal (shader-location = 2) glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); + glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_NORMAL]); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); glVertexAttribPointer(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(RLGL.State.currentShaderLocs[RL_SHADER_LOC_VERTEX_COLOR]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[3]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[4]); } // Setup some default shader values @@ -4880,6 +4949,31 @@ static int rlGetPixelDataSize(int width, int height, int format) // Auxiliar math functions +// Get float array of matrix data +static rl_float16 rlMatrixToFloatV(Matrix mat) +{ + rl_float16 result = { 0 }; + + result.v[0] = mat.m0; + result.v[1] = mat.m1; + result.v[2] = mat.m2; + result.v[3] = mat.m3; + result.v[4] = mat.m4; + result.v[5] = mat.m5; + result.v[6] = mat.m6; + result.v[7] = mat.m7; + result.v[8] = mat.m8; + result.v[9] = mat.m9; + result.v[10] = mat.m10; + result.v[11] = mat.m11; + result.v[12] = mat.m12; + result.v[13] = mat.m13; + result.v[14] = mat.m14; + result.v[15] = mat.m15; + + return result; +} + // Get identity matrix static Matrix rlMatrixIdentity(void) { @@ -4919,4 +5013,76 @@ static Matrix rlMatrixMultiply(Matrix left, Matrix right) return result; } +// Transposes provided matrix +static Matrix rlMatrixTranspose(Matrix mat) +{ + Matrix result = { 0 }; + + result.m0 = mat.m0; + result.m1 = mat.m4; + result.m2 = mat.m8; + result.m3 = mat.m12; + result.m4 = mat.m1; + result.m5 = mat.m5; + result.m6 = mat.m9; + result.m7 = mat.m13; + result.m8 = mat.m2; + result.m9 = mat.m6; + result.m10 = mat.m10; + result.m11 = mat.m14; + result.m12 = mat.m3; + result.m13 = mat.m7; + result.m14 = mat.m11; + result.m15 = mat.m15; + + return result; +} + +// Invert provided matrix +static Matrix rlMatrixInvert(Matrix mat) +{ + Matrix result = { 0 }; + + // Cache the matrix values (speed optimization) + float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; + float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; + float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; + + float b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the invert determinant (inlined to avoid double-caching) + float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + + result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; + result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; + result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; + result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; + result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; + result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; + result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; + result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; + result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; + result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; + result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; + result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; + result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; + result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; + result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; + result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; + + return result; +} + #endif // RLGL_IMPLEMENTATION