| @@ -61,19 +61,7 @@ void nvgDeleteGL3(struct NVGcontext* ctx); | |||||
| enum GLNVGuniformLoc { | enum GLNVGuniformLoc { | ||||
| GLNVG_LOC_UBOVIEW, | GLNVG_LOC_UBOVIEW, | ||||
| GLNVG_LOC_SCISSORMAT, | |||||
| GLNVG_LOC_SCISSOREXT, | |||||
| GLNVG_LOC_SCISSORSCALE, | |||||
| GLNVG_LOC_PAINTMAT, | |||||
| GLNVG_LOC_EXTENT, | |||||
| GLNVG_LOC_RADIUS, | |||||
| GLNVG_LOC_FEATHER, | |||||
| GLNVG_LOC_INNERCOL, | |||||
| GLNVG_LOC_OUTERCOL, | |||||
| GLNVG_LOC_STROKEMULT, | |||||
| GLNVG_LOC_TEX, | |||||
| GLNVG_LOC_TEXTYPE, | |||||
| GLNVG_LOC_TYPE, | |||||
| GLNVG_LOC_UBOFRAG, | |||||
| GLNVG_MAX_LOCS | GLNVG_MAX_LOCS | ||||
| }; | }; | ||||
| @@ -86,6 +74,7 @@ enum GLNVGshaderType { | |||||
| enum GLNVGuniformBindings { | enum GLNVGuniformBindings { | ||||
| GLNVG_UBO_VIEW_BINDING = 0, | GLNVG_UBO_VIEW_BINDING = 0, | ||||
| GLNVG_UBO_FRAG_BINDING = 1, | |||||
| }; | }; | ||||
| struct GLNVGshader { | struct GLNVGshader { | ||||
| @@ -127,6 +116,21 @@ struct GLNVGpath { | |||||
| int convex; | int convex; | ||||
| }; | }; | ||||
| struct GLNVGuboFrag { | |||||
| float scissorMat[12]; // matrices are actually 3 vec4s | |||||
| float paintMat[12]; | |||||
| float innerCol[4]; | |||||
| float outerCol[4]; | |||||
| float scissorExt[2]; | |||||
| float scissorScale[2]; | |||||
| float extent[2]; | |||||
| float radius; | |||||
| float feather; | |||||
| float strokeMult; | |||||
| int texType; | |||||
| int type; | |||||
| }; | |||||
| struct GLNVGcontext { | struct GLNVGcontext { | ||||
| struct GLNVGshader shader; | struct GLNVGshader shader; | ||||
| struct GLNVGtexture* textures; | struct GLNVGtexture* textures; | ||||
| @@ -137,6 +141,8 @@ struct GLNVGcontext { | |||||
| GLuint vertArr; | GLuint vertArr; | ||||
| GLuint vertBuf; | GLuint vertBuf; | ||||
| GLuint uboViewBuf; | GLuint uboViewBuf; | ||||
| GLuint uboFragBuf; | |||||
| int uboPosAlignment; | |||||
| int edgeAntiAlias; | int edgeAntiAlias; | ||||
| struct GLNVGcall* calls; | struct GLNVGcall* calls; | ||||
| @@ -291,19 +297,7 @@ static void glnvg__deleteShader(struct GLNVGshader* shader) | |||||
| static void glnvg__getUniforms(struct GLNVGshader* shader) | static void glnvg__getUniforms(struct GLNVGshader* shader) | ||||
| { | { | ||||
| shader->loc[GLNVG_LOC_UBOVIEW] = glGetUniformBlockIndex(shader->prog, "uboView"); | shader->loc[GLNVG_LOC_UBOVIEW] = glGetUniformBlockIndex(shader->prog, "uboView"); | ||||
| shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat"); | |||||
| shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt"); | |||||
| shader->loc[GLNVG_LOC_SCISSORSCALE] = glGetUniformLocation(shader->prog, "scissorScale"); | |||||
| shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat"); | |||||
| shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent"); | |||||
| shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius"); | |||||
| shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather"); | |||||
| shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol"); | |||||
| shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol"); | |||||
| shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult"); | |||||
| shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex"); | |||||
| shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType"); | |||||
| shader->loc[GLNVG_LOC_TYPE] = glGetUniformLocation(shader->prog, "type"); | |||||
| shader->loc[GLNVG_LOC_UBOFRAG] = glGetUniformBlockIndex(shader->prog, "uboFrag"); | |||||
| } | } | ||||
| static int glnvg__renderCreate(void* uptr) | static int glnvg__renderCreate(void* uptr) | ||||
| @@ -337,19 +331,21 @@ static int glnvg__renderCreate(void* uptr) | |||||
| #else | #else | ||||
| "#version 150 core\n" | "#version 150 core\n" | ||||
| #endif | #endif | ||||
| "uniform mat3 scissorMat;\n" | |||||
| "uniform vec2 scissorExt;\n" | |||||
| "uniform vec2 scissorScale;\n" | |||||
| "uniform mat3 paintMat;\n" | |||||
| "uniform vec2 extent;\n" | |||||
| "uniform float radius;\n" | |||||
| "uniform float feather;\n" | |||||
| "uniform vec4 innerCol;\n" | |||||
| "uniform vec4 outerCol;\n" | |||||
| "uniform float strokeMult;\n" | |||||
| "layout(std140) uniform uboFrag {\n" | |||||
| " mat3 scissorMat;\n" | |||||
| " mat3 paintMat;\n" | |||||
| " vec4 innerCol;\n" | |||||
| " vec4 outerCol;\n" | |||||
| " vec2 scissorExt;\n" | |||||
| " vec2 scissorScale;\n" | |||||
| " vec2 extent;\n" | |||||
| " float radius;\n" | |||||
| " float feather;\n" | |||||
| " float strokeMult;\n" | |||||
| " int texType;\n" | |||||
| " int type;\n" | |||||
| "};\n" | |||||
| "uniform sampler2D tex;\n" | "uniform sampler2D tex;\n" | ||||
| "uniform int texType;\n" | |||||
| "uniform int type;\n" | |||||
| "in vec2 ftcoord;\n" | "in vec2 ftcoord;\n" | ||||
| "in vec2 fpos;\n" | "in vec2 fpos;\n" | ||||
| "out vec4 outColor;\n" | "out vec4 outColor;\n" | ||||
| @@ -409,19 +405,21 @@ static int glnvg__renderCreate(void* uptr) | |||||
| #else | #else | ||||
| "#version 150 core\n" | "#version 150 core\n" | ||||
| #endif | #endif | ||||
| "uniform mat3 scissorMat;\n" | |||||
| "uniform vec2 scissorExt;\n" | |||||
| "uniform vec2 scissorScale;\n" | |||||
| "uniform mat3 paintMat;\n" | |||||
| "uniform vec2 extent;\n" | |||||
| "uniform float radius;\n" | |||||
| "uniform float feather;\n" | |||||
| "uniform vec4 innerCol;\n" | |||||
| "uniform vec4 outerCol;\n" | |||||
| "uniform float strokeMult;\n" | |||||
| "layout(std140) uniform uboFrag {\n" | |||||
| " mat3 scissorMat;\n" | |||||
| " mat3 paintMat;\n" | |||||
| " vec4 innerCol;\n" | |||||
| " vec4 outerCol;\n" | |||||
| " vec2 scissorExt;\n" | |||||
| " vec2 scissorScale;\n" | |||||
| " vec2 extent;\n" | |||||
| " float radius;\n" | |||||
| " float feather;\n" | |||||
| " float strokeMult;\n" | |||||
| " int texType;\n" | |||||
| " int type;\n" | |||||
| "};\n" | |||||
| "uniform sampler2D tex;\n" | "uniform sampler2D tex;\n" | ||||
| "uniform int texType;\n" | |||||
| "uniform int type;\n" | |||||
| "in vec2 ftcoord;\n" | "in vec2 ftcoord;\n" | ||||
| "in vec2 fpos;\n" | "in vec2 fpos;\n" | ||||
| "out vec4 outColor;\n" | "out vec4 outColor;\n" | ||||
| @@ -487,6 +485,10 @@ static int glnvg__renderCreate(void* uptr) | |||||
| // Create UBOs | // Create UBOs | ||||
| glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_UBOVIEW], GLNVG_UBO_VIEW_BINDING); | glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_UBOVIEW], GLNVG_UBO_VIEW_BINDING); | ||||
| glGenBuffers(1, &gl->uboViewBuf); | glGenBuffers(1, &gl->uboViewBuf); | ||||
| glUniformBlockBinding(gl->shader.prog, gl->shader.loc[GLNVG_LOC_UBOFRAG], GLNVG_UBO_FRAG_BINDING); | |||||
| glGenBuffers(1, &gl->uboFragBuf); | |||||
| glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &gl->uboPosAlignment); | |||||
| gl->uboPosAlignment = sizeof( struct GLNVGuboFrag ) + gl->uboPosAlignment - sizeof( struct GLNVGuboFrag ) % gl->uboPosAlignment; | |||||
| glnvg__checkError("done"); | glnvg__checkError("done"); | ||||
| @@ -608,64 +610,76 @@ static void glnvg__xformToMat3x3(float* m3, float* t) | |||||
| m3[8] = 1.0f; | m3[8] = 1.0f; | ||||
| } | } | ||||
| static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width) | |||||
| static void glnvg__xformToMat3x4(float* m3, float* t) | |||||
| { | |||||
| m3[0] = t[0]; | |||||
| m3[1] = t[1]; | |||||
| m3[2] = 0.0f; | |||||
| m3[3] = 0.0f; | |||||
| m3[4] = t[2]; | |||||
| m3[5] = t[3]; | |||||
| m3[6] = 0.0f; | |||||
| m3[7] = 0.0f; | |||||
| m3[8] = t[4]; | |||||
| m3[9] = t[5]; | |||||
| m3[10] = 1.0f; | |||||
| m3[11] = 0.0f; | |||||
| } | |||||
| static int glnvg__setupPaintUBO(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width, struct GLNVGuboFrag* uboBuff) | |||||
| { | { | ||||
| float innerCol[4]; | |||||
| float outerCol[4]; | |||||
| glnvg__toFloatColor(innerCol, paint->innerColor); | |||||
| glnvg__toFloatColor(outerCol, paint->outerColor); | |||||
| struct GLNVGuboFrag ubo; | |||||
| glnvg__toFloatColor(ubo.innerCol, paint->innerColor); | |||||
| glnvg__toFloatColor(ubo.outerCol, paint->outerColor); | |||||
| struct GLNVGtexture* tex = NULL; | struct GLNVGtexture* tex = NULL; | ||||
| float invxform[6], paintMat[9], scissorMat[9]; | |||||
| float scissorx = 0, scissory = 0; | |||||
| float scissorsx = 0, scissorsy = 0; | |||||
| float invxform[6]; | |||||
| glnvg__xformInverse(invxform, paint->xform); | glnvg__xformInverse(invxform, paint->xform); | ||||
| glnvg__xformToMat3x3(paintMat, invxform); | |||||
| glnvg__xformToMat3x4(ubo.paintMat, invxform); | |||||
| if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) { | if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) { | ||||
| memset(scissorMat, 0, sizeof(scissorMat)); | |||||
| scissorx = 1.0f; | |||||
| scissory = 1.0f; | |||||
| scissorsx = 1.0f; | |||||
| scissorsy = 1.0f; | |||||
| memset(ubo.scissorMat, 0, sizeof(ubo.scissorMat)); | |||||
| ubo.scissorExt[0] = 1.0f; | |||||
| ubo.scissorExt[1] = 1.0f; | |||||
| ubo.scissorScale[0] = 1.0f; | |||||
| ubo.scissorScale[1] = 1.0f; | |||||
| } else { | } else { | ||||
| glnvg__xformInverse(invxform, scissor->xform); | glnvg__xformInverse(invxform, scissor->xform); | ||||
| glnvg__xformToMat3x3(scissorMat, invxform); | |||||
| scissorx = scissor->extent[0]; | |||||
| scissory = scissor->extent[1]; | |||||
| scissorsx = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]); | |||||
| scissorsy = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]); | |||||
| glnvg__xformToMat3x4(ubo.scissorMat, invxform); | |||||
| ubo.scissorExt[0] = scissor->extent[0]; | |||||
| ubo.scissorExt[1] = scissor->extent[1]; | |||||
| ubo.scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]); | |||||
| ubo.scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]); | |||||
| } | } | ||||
| memcpy( ubo.extent, paint->extent, sizeof( ubo.extent ) ); | |||||
| ubo.strokeMult = width*0.5f + 0.5f; | |||||
| if (paint->image != 0) { | if (paint->image != 0) { | ||||
| tex = glnvg__findTexture(gl, paint->image); | tex = glnvg__findTexture(gl, paint->image); | ||||
| if (tex == NULL) return 0; | if (tex == NULL) return 0; | ||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLIMG); | |||||
| glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy); | |||||
| glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]); | |||||
| glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + 0.5f); | |||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); | |||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1); | |||||
| ubo.type = NSVG_SHADER_FILLIMG; | |||||
| ubo.texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1; | |||||
| glnvg__checkError("tex paint loc"); | glnvg__checkError("tex paint loc"); | ||||
| glBindTexture(GL_TEXTURE_2D, tex->tex); | |||||
| glnvg__checkError("tex paint tex"); | |||||
| } else { | } else { | ||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLGRAD); | |||||
| glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy); | |||||
| glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat); | |||||
| glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]); | |||||
| glUniform1f(gl->shader.loc[GLNVG_LOC_RADIUS], paint->radius); | |||||
| glUniform1f(gl->shader.loc[GLNVG_LOC_FEATHER], paint->feather); | |||||
| glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, innerCol); | |||||
| glUniform4fv(gl->shader.loc[GLNVG_LOC_OUTERCOL], 1, outerCol); | |||||
| glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], width*0.5f + 0.5f); | |||||
| ubo.type = NSVG_SHADER_FILLGRAD; | |||||
| ubo.radius = paint->radius; | |||||
| ubo.feather = paint->feather; | |||||
| glnvg__checkError("grad paint loc"); | glnvg__checkError("grad paint loc"); | ||||
| } | } | ||||
| *uboBuff = ubo; | |||||
| return 1; | |||||
| } | |||||
| static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, int* uboPos) | |||||
| { | |||||
| glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); | |||||
| *uboPos += gl->uboPosAlignment; | |||||
| if (paint->image != 0) { | |||||
| struct GLNVGtexture* tex = glnvg__findTexture(gl, paint->image); | |||||
| if (tex == NULL) return 0; | |||||
| glBindTexture(GL_TEXTURE_2D, tex->tex); | |||||
| glnvg__checkError("tex paint tex"); | |||||
| } | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -676,14 +690,14 @@ static void glnvg__renderViewport(void* uptr, int width, int height) | |||||
| gl->view[1] = (float)height; | gl->view[1] = (float)height; | ||||
| } | } | ||||
| static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos ) | |||||
| { | { | ||||
| struct GLNVGpath* paths = &gl->paths[call->pathOffset]; | struct GLNVGpath* paths = &gl->paths[call->pathOffset]; | ||||
| int npaths = call->pathCount, offset, i; | |||||
| int npaths = call->pathCount, i; | |||||
| if (npaths == 1 && paths[0].convex) { | if (npaths == 1 && paths[0].convex) { | ||||
| glnvg__setupPaint(gl, &call->paint, &call->scissor, 1.0001f); | |||||
| glnvg__setupPaint(gl, &call->paint, uboPos); | |||||
| for (i = 0; i < npaths; i++) { | for (i = 0; i < npaths; i++) { | ||||
| glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); | glDrawArrays(GL_TRIANGLE_FAN, paths[i].fillOffset, paths[i].fillCount); | ||||
| @@ -705,7 +719,9 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| glStencilFunc(GL_ALWAYS, 0, ~0); | glStencilFunc(GL_ALWAYS, 0, ~0); | ||||
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); | ||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_SIMPLE); | |||||
| // set bindpoint for solid loc | |||||
| glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); | |||||
| *uboPos += gl->uboPosAlignment; | |||||
| glnvg__checkError("fill solid loc"); | glnvg__checkError("fill solid loc"); | ||||
| glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); | glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); | ||||
| @@ -720,7 +736,7 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||||
| glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
| glnvg__setupPaint(gl, &call->paint, &call->scissor, 1.0001f); | |||||
| glnvg__setupPaint(gl, &call->paint, uboPos); | |||||
| if (gl->edgeAntiAlias) { | if (gl->edgeAntiAlias) { | ||||
| glStencilFunc(GL_EQUAL, 0x00, 0xff); | glStencilFunc(GL_EQUAL, 0x00, 0xff); | ||||
| @@ -741,12 +757,12 @@ static void glnvg__fill(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| } | } | ||||
| } | } | ||||
| static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos) | |||||
| { | { | ||||
| struct GLNVGpath* paths = &gl->paths[call->pathOffset]; | struct GLNVGpath* paths = &gl->paths[call->pathOffset]; | ||||
| int npaths = call->pathCount, offset, i; | |||||
| int npaths = call->pathCount, i; | |||||
| glnvg__setupPaint(gl, &call->paint, &call->scissor, call->strokeWidth); | |||||
| glnvg__setupPaint(gl, &call->paint, uboPos); | |||||
| // Draw Strokes | // Draw Strokes | ||||
| for (i = 0; i < npaths; i++) { | for (i = 0; i < npaths; i++) { | ||||
| @@ -754,21 +770,15 @@ static void glnvg__stroke(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| } | } | ||||
| } | } | ||||
| static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call, int* uboPos) | |||||
| { | { | ||||
| struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); | struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); | ||||
| int offset = call->triangleOffset * sizeof(struct NVGvertex); | |||||
| float color[4]; | |||||
| if (tex != NULL) { | if (tex != NULL) { | ||||
| glBindTexture(GL_TEXTURE_2D, tex->tex); | glBindTexture(GL_TEXTURE_2D, tex->tex); | ||||
| } | } | ||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_IMG); | |||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0); | |||||
| glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1); | |||||
| glnvg__toFloatColor(color, call->paint.innerColor); | |||||
| glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, color ); | |||||
| glBindBufferRange( GL_UNIFORM_BUFFER, GLNVG_UBO_FRAG_BINDING, gl->uboFragBuf, *uboPos, sizeof(struct GLNVGuboFrag)); | |||||
| *uboPos += gl->uboPosAlignment; | |||||
| glnvg__checkError("tris solid img loc"); | glnvg__checkError("tris solid img loc"); | ||||
| @@ -778,13 +788,46 @@ static void glnvg__triangles(struct GLNVGcontext* gl, struct GLNVGcall* call) | |||||
| static void glnvg__renderFlush(void* uptr) | static void glnvg__renderFlush(void* uptr) | ||||
| { | { | ||||
| struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; | struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr; | ||||
| int i; | |||||
| int i, uboPos; | |||||
| if (gl->ncalls > 0) { | if (gl->ncalls > 0) { | ||||
| glUseProgram(gl->shader.prog); | glUseProgram(gl->shader.prog); | ||||
| glEnable(GL_CULL_FACE); | glEnable(GL_CULL_FACE); | ||||
| // upload ubo for frag shaders - maximum ubos is 2x num calls | |||||
| glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf); | |||||
| glBufferData(GL_UNIFORM_BUFFER, 2 * gl->ncalls * sizeof(struct GLNVGuboFrag), 0, GL_STREAM_DRAW); | |||||
| char* buff = glMapBuffer( GL_UNIFORM_BUFFER, GL_WRITE_ONLY ); | |||||
| for (i = 0; i < gl->ncalls; i++) { | |||||
| struct GLNVGcall* call = &gl->calls[i]; | |||||
| struct GLNVGuboFrag* ubo = (struct GLNVGuboFrag*)buff; | |||||
| if (call->type == GLNVG_FILL) | |||||
| { | |||||
| if (!(call->pathCount == 1 && gl->paths[call->pathOffset].convex)) { | |||||
| ubo->type = NSVG_SHADER_SIMPLE; | |||||
| buff += gl->uboPosAlignment;; | |||||
| ubo = (struct GLNVGuboFrag*)buff; | |||||
| } | |||||
| glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, 1.0001f, ubo); | |||||
| buff += gl->uboPosAlignment; | |||||
| } | |||||
| else if (call->type == GLNVG_STROKE) | |||||
| { | |||||
| glnvg__setupPaintUBO(gl, &call->paint, &call->scissor, call->strokeWidth, ubo); | |||||
| buff += gl->uboPosAlignment; | |||||
| } | |||||
| else if (call->type == GLNVG_TRIANGLES) | |||||
| { | |||||
| struct GLNVGtexture* tex = glnvg__findTexture(gl, call->paint.image); | |||||
| glnvg__toFloatColor(ubo->innerCol, call->paint.innerColor); | |||||
| ubo->texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1; | |||||
| ubo->type = NSVG_SHADER_IMG; | |||||
| buff += gl->uboPosAlignment; | |||||
| } | |||||
| } | |||||
| glUnmapBuffer(GL_UNIFORM_BUFFER); | |||||
| // Upload vertex data | // Upload vertex data | ||||
| glBindVertexArray(gl->vertArr); | glBindVertexArray(gl->vertArr); | ||||
| glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); | glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf); | ||||
| @@ -800,14 +843,17 @@ static void glnvg__renderFlush(void* uptr) | |||||
| glBufferData(GL_UNIFORM_BUFFER, sizeof(gl->view), gl->view, GL_STREAM_DRAW); | glBufferData(GL_UNIFORM_BUFFER, sizeof(gl->view), gl->view, GL_STREAM_DRAW); | ||||
| glBindBufferBase(GL_UNIFORM_BUFFER, GLNVG_UBO_VIEW_BINDING, gl->uboViewBuf); | glBindBufferBase(GL_UNIFORM_BUFFER, GLNVG_UBO_VIEW_BINDING, gl->uboViewBuf); | ||||
| glBindBuffer(GL_UNIFORM_BUFFER, gl->uboFragBuf); | |||||
| uboPos = 0; | |||||
| for (i = 0; i < gl->ncalls; i++) { | for (i = 0; i < gl->ncalls; i++) { | ||||
| struct GLNVGcall* call = &gl->calls[i]; | struct GLNVGcall* call = &gl->calls[i]; | ||||
| if (call->type == GLNVG_FILL) | if (call->type == GLNVG_FILL) | ||||
| glnvg__fill(gl, call); | |||||
| glnvg__fill(gl, call, &uboPos); | |||||
| else if (call->type == GLNVG_STROKE) | else if (call->type == GLNVG_STROKE) | ||||
| glnvg__stroke(gl, call); | |||||
| glnvg__stroke(gl, call, &uboPos); | |||||
| else if (call->type == GLNVG_TRIANGLES) | else if (call->type == GLNVG_TRIANGLES) | ||||
| glnvg__triangles(gl, call); | |||||
| glnvg__triangles(gl, call, &uboPos); | |||||
| } | } | ||||
| glDisableVertexAttribArray(0); | glDisableVertexAttribArray(0); | ||||