diff --git a/src/charset.cpp b/src/charset.cpp index 601115e..f9208b3 100644 --- a/src/charset.cpp +++ b/src/charset.cpp @@ -56,7 +56,9 @@ void Charset::close(void) { rwFree(indices); + indices = nil; rwFree(vertices); + vertices = nil; } Charset* diff --git a/src/d3d/d3d9matfx.cpp b/src/d3d/d3d9matfx.cpp index 500107e..35a4adf 100644 --- a/src/d3d/d3d9matfx.cpp +++ b/src/d3d/d3d9matfx.cpp @@ -159,7 +159,7 @@ matfxRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) bool normals = !!(atomic->geometry->flags & Geometry::NORMALS); float surfProps[4]; - surfProps[3] = atomic->geometry->flags&Geometry::PRELIT ? 1.0f : 0.0f; + surfProps[3] = 0.0f; InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp index 494cc92..e182e98 100644 --- a/src/d3d/d3d9render.cpp +++ b/src/d3d/d3d9render.cpp @@ -89,10 +89,9 @@ defaultRenderCB_Fix(Atomic *atomic, InstanceDataHeader *header) convMatrix(&world, f->getLTM()); d3ddevice->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&world); - setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, - 0, header->vertexStream[0].stride); - setIndices((IDirect3DIndexBuffer9*)header->indexBuffer); - setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); + setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); + setIndices(header->indexBuffer); + setVertexDeclaration(header->vertexDeclaration); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -145,10 +144,9 @@ void defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) { int vsBits; - setStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer, - 0, header->vertexStream[0].stride); - setIndices((IDirect3DIndexBuffer9*)header->indexBuffer); - setVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration); + setStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride); + setIndices(header->indexBuffer); + setVertexDeclaration(header->vertexDeclaration); vsBits = lightingCB_Shader(atomic); uploadMatrices(atomic->getFrame()->getLTM()); @@ -165,7 +163,7 @@ defaultRenderCB_Shader(Atomic *atomic, InstanceDataHeader *header) setVertexShader(default_all_VS); float surfProps[4]; - surfProps[3] = atomic->geometry->flags&Geometry::PRELIT ? 1.0f : 0.0f; + surfProps[3] = 0.0f; InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ diff --git a/src/d3d/d3d9skin.cpp b/src/d3d/d3d9skin.cpp index b99d795..e45d68a 100644 --- a/src/d3d/d3d9skin.cpp +++ b/src/d3d/d3d9skin.cpp @@ -288,7 +288,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) setVertexShader(skin_all_VS); float surfProps[4]; - surfProps[3] = atomic->geometry->flags&Geometry::PRELIT ? 1.0f : 0.0f; + surfProps[3] = 0.0f; InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ diff --git a/src/d3d/d3dimmed.cpp b/src/d3d/d3dimmed.cpp index 7a5e47b..db18af3 100644 --- a/src/d3d/d3dimmed.cpp +++ b/src/d3d/d3dimmed.cpp @@ -37,6 +37,8 @@ static IDirect3DVertexDeclaration9 *im2ddecl; static IDirect3DVertexBuffer9 *im2dvertbuf; static IDirect3DIndexBuffer9 *im2dindbuf; +void *im2dOverridePS; + void openIm2D(void) { @@ -111,7 +113,9 @@ im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices) setStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex)); setVertexDeclaration(im2ddecl); - if(engine->device.getRenderState(TEXTURERASTER)) + if(im2dOverridePS) + setPixelShader(im2dOverridePS); + else if(engine->device.getRenderState(TEXTURERASTER)) setPixelShader(im2d_tex_PS); else setPixelShader(im2d_PS); @@ -163,7 +167,9 @@ im2DRenderIndexedPrimitive(PrimitiveType primType, setIndices(im2dindbuf); setVertexDeclaration(im2ddecl); - if(engine->device.getRenderState(TEXTURERASTER)) + if(im2dOverridePS) + setPixelShader(im2dOverridePS); + else if(engine->device.getRenderState(TEXTURERASTER)) setPixelShader(im2d_tex_PS); else setPixelShader(im2d_PS); diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 06bd6ba..9ee270d 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -263,6 +263,8 @@ void uploadMatrices(void); // no world transform void uploadMatrices(Matrix *worldMat); int32 uploadLights(WorldLights *lightData); // called by lightingCB_Shader +extern void *im2dOverridePS; + extern void *default_amb_VS; extern void *default_amb_dir_VS; extern void *default_all_VS; diff --git a/src/d3d/shaders/matfx_env_VS.hlsl b/src/d3d/shaders/matfx_env_VS.hlsl index 4521855..73179ab 100644 --- a/src/d3d/shaders/matfx_env_VS.hlsl +++ b/src/d3d/shaders/matfx_env_VS.hlsl @@ -23,11 +23,11 @@ VS_out main(in VS_in input) VS_out output; output.Position = mul(combinedMat, input.Position); - float3 Vertex = mul(worldMat, input.Position).xyz; - float3 Normal = mul(normalMat, input.Normal); + float3 V = mul(worldMat, input.Position).xyz; + float3 N = mul(normalMat, input.Normal); output.TexCoord0.xy = input.TexCoord; - output.TexCoord1 = mul(texMat, float4(Normal, 1.0)).xy; + output.TexCoord1 = mul(texMat, float4(N, 1.0)).xy; output.Color = input.Prelight; output.Color.rgb += ambientLight.rgb * surfAmbient; @@ -35,15 +35,15 @@ VS_out main(in VS_in input) int i; #ifdef DIRECTIONALS for(i = 0; i < numDirLights; i++) - output.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse; + output.Color.xyz += DoDirLight(lights[i+firstDirLight], N)*surfDiffuse; #endif #ifdef POINTLIGHTS for(i = 0; i < numPointLights; i++) - output.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse; + output.Color.xyz += DoPointLight(lights[i+firstPointLight], V, N)*surfDiffuse; #endif #ifdef SPOTLIGHTS for(i = 0; i < numSpotLights; i++) - output.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse; + output.Color.xyz += DoSpotLight(lights[i+firstSpotLight], V, N)*surfDiffuse; #endif // PS2 clamps before material color output.Color = clamp(output.Color, 0.0, 1.0); diff --git a/src/engine.cpp b/src/engine.cpp index 052dab6..310c89d 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -293,6 +293,10 @@ Engine::term(void) PluginList::close(); + // This has to be reset because it won't be opened again otherwise + // TODO: maybe reset more stuff here? + d3d::nativeRasterOffset = 0; + #ifdef TRACK_ALLOCATIONS FORLIST(lnk, allocations){ MemoryBlock *mem = LLLinkGetData(lnk, MemoryBlock, inAllocList); diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 328f171..53c5446 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -62,10 +62,13 @@ struct UniformState { int32 alphaFunc; float32 alphaRef; - int32 fogEnable; float32 fogStart; float32 fogEnd; - int32 pad[3]; + + float32 fogRange; + float32 fogDisable; + int32 pad[2]; + RGBAf fogColor; }; @@ -77,14 +80,10 @@ struct UniformScene struct UniformLight { - V3d position; - float32 w; - V3d direction; - int32 pad1; - RGBAf color; - float32 radius; - float32 minusCosAngle; - int32 pad2[2]; + float32 enabled, radius, minusCosAngle, hardSpot; + V3d position; int32 pad0; + V3d direction; int32 pad1; + RGBAf color; }; #define MAX_LIGHTS 8 @@ -93,9 +92,9 @@ struct UniformObject { RawMatrix world; RGBAf ambLight; - int32 numLights; - int32 pad[3]; - UniformLight lights[MAX_LIGHTS]; + UniformLight directLights[MAX_LIGHTS]; + UniformLight pointLights[MAX_LIGHTS]; + UniformLight spotLights[MAX_LIGHTS]; }; static GLuint vao; @@ -106,9 +105,9 @@ static UniformScene uniformScene; static UniformObject uniformObject; int32 u_matColor; -int32 u_surfaceProps; +int32 u_surfProps; -Shader *simpleShader; +Shader *defaultShader; static bool32 stateDirty = 1; static bool32 sceneDirty = 1; @@ -133,6 +132,9 @@ struct RwStateCache { uint32 zwrite; uint32 ztest; uint32 cullmode; + uint32 fogEnable; + float32 fogStart; + float32 fogEnd; RwRasterStateCache texstage[MAXNUMSTAGES]; }; static RwStateCache rwStateCache; @@ -155,6 +157,41 @@ static uint32 blendMap[] = { GL_SRC_ALPHA_SATURATE, }; +static void +setDepthTest(bool32 enable) +{ + if(rwStateCache.ztest != enable){ + rwStateCache.ztest = enable; + if(rwStateCache.zwrite && !enable){ + // If we still want to write, enable but set mode to always + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + }else{ + if(rwStateCache.ztest) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + } + + } +} + +static void +setDepthWrite(bool32 enable) +{ + enable = enable ? GL_TRUE : GL_FALSE; + if(rwStateCache.zwrite != enable){ + rwStateCache.zwrite = enable; + if(enable && !rwStateCache.ztest){ + // Have to switch on ztest so writing can work + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + } + glDepthMask(rwStateCache.zwrite); + } +} + static void setAlphaTest(bool32 enable) { @@ -412,23 +449,14 @@ setRenderState(int32 state, void *pvalue) } break; case ZTESTENABLE: - if(rwStateCache.ztest != value){ - rwStateCache.ztest = value; - if(rwStateCache.ztest) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); - } + setDepthTest(value); break; case ZWRITEENABLE: - if(rwStateCache.zwrite != (value ? GL_TRUE : GL_FALSE)){ - rwStateCache.zwrite = value ? GL_TRUE : GL_FALSE; - glDepthMask(rwStateCache.zwrite); - } + setDepthWrite(value); break; case FOGENABLE: - if(uniformState.fogEnable != value){ - uniformState.fogEnable = value; + if(rwStateCache.fogEnable != value){ + rwStateCache.fogEnable = value; stateDirty = 1; } break; @@ -506,7 +534,7 @@ getRenderState(int32 state) val = rwStateCache.zwrite; break; case FOGENABLE: - val = uniformState.fogEnable; + val = rwStateCache.fogEnable; break; case FOGCOLOR: convColor(&rgba, &uniformState.fogColor); @@ -534,8 +562,10 @@ resetRenderState(void) rwStateCache.alphaFunc = ALPHAGREATEREQUAL; uniformState.alphaFunc = 0; uniformState.alphaRef = 10.0f/255.0f; - uniformState.fogEnable = 0; + uniformState.fogDisable = 1.0f; uniformState.fogStart = 0.0f; + uniformState.fogEnd = 0.0f; + uniformState.fogRange = 0.0f; uniformState.fogColor = { 1.0f, 1.0f, 1.0f, 1.0f }; stateDirty = 1; @@ -573,40 +603,66 @@ setWorldMatrix(Matrix *mat) objectDirty = 1; } -void -setAmbientLight(RGBAf *amb) +int32 +setLights(WorldLights *lightData) { - uniformObject.ambLight = *amb; - objectDirty = 1; -} + int i, np, ns; + Light *l; + int32 bits; -void -setNumLights(int32 n) -{ - uniformObject.numLights = n; - objectDirty = 1; -} + uniformObject.ambLight = lightData->ambient; + memset(uniformObject.directLights, 0, sizeof(uniformObject.directLights)); + memset(uniformObject.pointLights, 0, sizeof(uniformObject.pointLights)); + memset(uniformObject.spotLights, 0, sizeof(uniformObject.spotLights)); -void -setLight(int32 n, Light *light) -{ - UniformLight *l; - Frame *f; - Matrix *m; + bits = 0; - l = &uniformObject.lights[n]; - f = light->getFrame(); - if(f){ - m = f->getLTM(); - l->position = m->pos; - l->direction = m->at; + for(i = 0; i < lightData->numDirectionals && i < 8; i++){ + l = lightData->directionals[i]; + uniformObject.directLights[i].enabled = 1.0f; + uniformObject.directLights[i].color = l->color; + uniformObject.directLights[i].direction = l->getFrame()->getLTM()->at; + bits |= VSLIGHT_POINT; } - // light has position - l->w = light->getType() >= Light::POINT ? 1.0f : 0.0f; - l->color = light->color; - l->radius = light->radius; - l->minusCosAngle = light->minusCosAngle; + + np = 0; + ns = 0; + for(i = 0; i < lightData->numLocals; i++){ + l = lightData->locals[i]; + switch(l->getType()){ + case Light::POINT: + if(np >= 8) + continue; + uniformObject.pointLights[np].enabled = 1.0f; + uniformObject.pointLights[np].color = l->color; + uniformObject.pointLights[np].position = l->getFrame()->getLTM()->pos; + uniformObject.pointLights[np].radius = l->radius; + np++; + bits |= VSLIGHT_POINT; + break; + + case Light::SPOT: + case Light::SOFTSPOT: + if(np >= 8) + continue; + uniformObject.spotLights[ns].enabled = 1.0f; + uniformObject.spotLights[ns].color = l->color; + uniformObject.spotLights[ns].position = l->getFrame()->getLTM()->pos; + uniformObject.spotLights[ns].direction = l->getFrame()->getLTM()->at; + uniformObject.spotLights[ns].radius = l->radius; + uniformObject.spotLights[ns].minusCosAngle = l->minusCosAngle; + if(l->getType() == Light::SOFTSPOT) + uniformObject.spotLights[ns].hardSpot = 0.0f; + else + uniformObject.spotLights[ns].hardSpot = 1.0f; + ns++; + bits |= VSLIGHT_SPOT; + break; + } + } + objectDirty = 1; + return 0; } void @@ -639,6 +695,10 @@ flushCache(void) sceneDirty = 0; } if(stateDirty){ + uniformState.fogDisable = rwStateCache.fogEnable ? 0.0f : 1.0f; + uniformState.fogStart = rwStateCache.fogStart; + uniformState.fogEnd = rwStateCache.fogEnd; + uniformState.fogRange = 1.0f/(rwStateCache.fogStart - rwStateCache.fogEnd); glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformState), &uniformState); @@ -762,12 +822,12 @@ beginUpdate(Camera *cam) memcpy(&cam->devProj, &proj, sizeof(RawMatrix)); setProjectionMatrix(proj); - if(uniformState.fogStart != cam->fogPlane){ - uniformState.fogStart = cam->fogPlane; + if(rwStateCache.fogStart != cam->fogPlane){ + rwStateCache.fogStart = cam->fogPlane; stateDirty = 1; } - if(uniformState.fogEnd != cam->farPlane){ - uniformState.fogEnd = cam->farPlane; + if(rwStateCache.fogEnd != cam->farPlane){ + rwStateCache.fogEnd = cam->farPlane; stateDirty = 1; } @@ -993,7 +1053,7 @@ initOpenGL(void) registerBlock("Object"); registerBlock("State"); u_matColor = registerUniform("u_matColor"); - u_surfaceProps = registerUniform("u_surfaceProps"); + u_surfProps = registerUniform("u_surfProps"); glClearColor(0.25, 0.25, 0.25, 1.0); @@ -1031,9 +1091,12 @@ initOpenGL(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); -#include "shaders/simple_vs_gl3.inc" +#include "shaders/default_vs_gl3.inc" #include "shaders/simple_fs_gl3.inc" - simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); + const char *vs[] = { header_vert_src, default_vert_src, nil }; + const char *fs[] = { simple_frag_src, nil }; + defaultShader = Shader::create(vs, fs); + assert(defaultShader); openIm2D(); openIm3D(); diff --git a/src/gl/gl3immed.cpp b/src/gl/gl3immed.cpp index 90cb69a..8cb62d9 100644 --- a/src/gl/gl3immed.cpp +++ b/src/gl/gl3immed.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "../rwbase.h" #include "../rwerror.h" @@ -50,7 +51,10 @@ openIm2D(void) #include "shaders/im2d_gl3.inc" #include "shaders/simple_fs_gl3.inc" - im2dShader = Shader::fromStrings(im2d_vert_src, simple_frag_src); + const char *vs[] = { header_vert_src, im2d_vert_src, nil }; + const char *fs[] = { simple_frag_src, nil }; + im2dShader = Shader::create(vs, fs); + assert(im2dShader); glGenBuffers(1, &im2DIbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); @@ -176,7 +180,10 @@ openIm3D(void) { #include "shaders/im3d_gl3.inc" #include "shaders/simple_fs_gl3.inc" - im3dShader = Shader::fromStrings(im3d_vert_src, simple_frag_src); + const char *vs[] = { header_vert_src, im3d_vert_src, nil }; + const char *fs[] = { simple_frag_src, nil }; + im3dShader = Shader::create(vs, fs); + assert(im3dShader); glGenBuffers(1, &im3DIbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo); diff --git a/src/gl/gl3matfx.cpp b/src/gl/gl3matfx.cpp index 51aa60f..8f9ecba 100644 --- a/src/gl/gl3matfx.cpp +++ b/src/gl/gl3matfx.cpp @@ -37,9 +37,14 @@ matfxOpen(void *o, int32, int32) { u_texMatrix = registerUniform("u_texMatrix"); u_coefficient = registerUniform("u_coefficient"); -#include "shaders/matfx_gl3.inc" matFXGlobals.pipelines[PLATFORM_GL3] = makeMatFXPipeline(); - envShader = Shader::fromStrings(matfx_env_vert_src, matfx_env_frag_src); + +#include "shaders/matfx_gl3.inc" + const char *vs[] = { header_vert_src, matfx_env_vert_src, nil }; + const char *fs[] = { matfx_env_frag_src, nil }; + envShader = Shader::create(vs, fs); + assert(envShader); + return o; } @@ -65,7 +70,7 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst) GLfloat surfProps[4]; m = inst->material; - simpleShader->use(); + defaultShader->use(); convColor(&col, &m->color); glUniform4fv(U(u_matColor), 1, (GLfloat*)&col); @@ -74,7 +79,7 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst) surfProps[1] = m->surfaceProps.specular; surfProps[2] = m->surfaceProps.diffuse; surfProps[3] = 0.0f; - glUniform4fv(U(u_surfaceProps), 1, surfProps); + glUniform4fv(U(u_surfProps), 1, surfProps); setTexture(0, m->texture); @@ -85,82 +90,54 @@ matfxDefaultRender(InstanceDataHeader *header, InstanceData *inst) GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); } +static Frame *lastEnvFrame; + +static RawMatrix normal2texcoord = { + { 0.5f, 0.0f, 0.0f }, 0.0f, + { 0.0f, -0.5f, 0.0f }, 0.0f, + { 0.0f, 0.0f, 1.0f }, 0.0f, + { 0.5f, 0.5f, 0.0f }, 1.0f +}; + void -calcEnvTexMatrix(Frame *f, float32 *mat) +uploadEnvMatrix(Frame *frame) { - Matrix cam; - if(f){ - // PS2 style - could be simplified by the shader - cam = *((Camera*)engine->currentCamera)->getFrame()->getLTM(); - cam.pos = { 0.0, 0.0, 0.0 }; - cam.right.x = -cam.right.x; - cam.right.y = -cam.right.y; - cam.right.z = -cam.right.z; + Matrix invMat; + if(frame == nil) + frame = engine->currentCamera->getFrame(); - Matrix inv; - Matrix::invert(&inv, f->getLTM()); - inv.pos = { -1.0, -1.0, -1.0 }; - inv.right.x *= -0.5f; - inv.right.y *= -0.5f; - inv.right.z *= -0.5f; - inv.up.x *= -0.5f; - inv.up.y *= -0.5f; - inv.up.z *= -0.5f; - inv.at.x *= -0.5f; - inv.at.y *= -0.5f; - inv.at.z *= -0.5f; - inv.pos.x *= -0.5f; - inv.pos.y *= -0.5f; - inv.pos.z *= -0.5f; + // cache the matrix across multiple meshes + static RawMatrix envMtx; + if(frame != lastEnvFrame){ + lastEnvFrame = frame; - Matrix m; - Matrix::mult(&m, &cam, &inv); - - memcpy(mat, &m, 64); - mat[3] = mat[7] = mat[11] = 0.0f; - mat[15] = 1.0f; - - }else{ - // D3D - TODO: find out what PS2 does - mat[0] = 0.5f; - mat[1] = 0.0f; - mat[2] = 0.0f; - mat[3] = 0.0f; - - mat[4] = 0.0f; - mat[5] = -0.5f; - mat[6] = 0.0f; - mat[7] = 0.0f; - - mat[8] = 0.0f; - mat[9] = 0.0f; - mat[10] = 1.0f; - mat[11] = 0.0f; - - mat[12] = 0.5f; - mat[13] = 0.5f; - mat[14] = 0.0f; - mat[15] = 0.0f; + RawMatrix invMtx; + Matrix::invert(&invMat, frame->getLTM()); + convMatrix(&invMtx, &invMat); + RawMatrix::mult(&envMtx, &invMtx, &normal2texcoord); } + glUniformMatrix4fv(U(u_texMatrix), 1, GL_FALSE, (float*)&envMtx); } void -matfxEnvRender(InstanceDataHeader *header, InstanceData *inst) +matfxEnvRender(InstanceDataHeader *header, InstanceData *inst, MatFX::Env *env) { Material *m; RGBAf col; GLfloat surfProps[4]; - float32 texMat[16]; m = inst->material; - matfxDefaultRender(header, inst); - - MatFX *fx = MatFX::get(m); - int32 idx = fx->getEffectIndex(MatFX::ENVMAP); - MatFX::Env *env = &fx->fx[idx].env; + if(env->tex == nil || env->coefficient == 0.0f){ + matfxDefaultRender(header, inst); + return; + } envShader->use(); + setTexture(0, m->texture); + setTexture(1, env->tex); + uploadEnvMatrix(env->frame); + convColor(&col, &m->color); glUniform4fv(U(u_matColor), 1, (GLfloat*)&col); @@ -168,52 +145,47 @@ matfxEnvRender(InstanceDataHeader *header, InstanceData *inst) surfProps[1] = m->surfaceProps.specular; surfProps[2] = m->surfaceProps.diffuse; surfProps[3] = 0.0f; - glUniform4fv(U(u_surfaceProps), 1, surfProps); + glUniform4fv(U(u_surfProps), 1, surfProps); glUniform1fv(U(u_coefficient), 1, &env->coefficient); - calcEnvTexMatrix(env->frame, texMat); - glUniformMatrix4fv(U(u_texMatrix), 1, GL_FALSE, texMat); - - setTexture(0, env->tex); - rw::SetRenderState(VERTEXALPHA, 1); rw::SetRenderState(SRCBLEND, BLENDONE); - rw::SetRenderState(DESTBLEND, BLENDONE); flushCache(); glDrawElements(header->primType, inst->numIndex, GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset); rw::SetRenderState(SRCBLEND, BLENDSRCALPHA); - rw::SetRenderState(DESTBLEND, BLENDINVSRCALPHA); } void matfxRenderCB(Atomic *atomic, InstanceDataHeader *header) { setWorldMatrix(atomic->getFrame()->getLTM()); - lightingCB(!!(atomic->geometry->flags & Geometry::NORMALS)); + lightingCB(atomic); glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); setAttribPointers(header->attribDesc, header->numAttribs); + lastEnvFrame = nil; + InstanceData *inst = header->inst; int32 n = header->numMeshes; -// rw::SetRenderState(ALPHATESTFUNC, 1); -// rw::SetRenderState(ALPHATESTREF, 50); - - int32 fx; while(n--){ - fx = MatFX::getEffects(inst->material); - switch(fx){ + MatFX *matfx = MatFX::get(inst->material); + + if(matfx == nil) + matfxDefaultRender(header, inst); + else switch(matfx->type){ case MatFX::ENVMAP: - matfxEnvRender(header, inst); + matfxEnvRender(header, inst, &matfx->fx[0].env); break; default: matfxDefaultRender(header, inst); + break; } inst++; } diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 7bb833f..6b9064d 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -44,7 +44,7 @@ rasterCreateTexture(Raster *raster) // TODO: check if this is correct natras->internalFormat = GL_RGBA; natras->format = GL_RGBA; - natras->type = GL_UNSIGNED_SHORT_5_5_5_1; + natras->type = GL_UNSIGNED_SHORT_1_5_5_5_REV; natras->hasAlpha = 1; break; default: @@ -96,7 +96,7 @@ rasterCreateCameraTexture(Raster *raster) // TODO: check if this is correct natras->internalFormat = GL_RGBA; natras->format = GL_RGBA; - natras->type = GL_UNSIGNED_SHORT_5_5_5_1; + natras->type = GL_UNSIGNED_SHORT_1_5_5_5_REV; natras->hasAlpha = 1; break; } @@ -242,12 +242,23 @@ imageFindRasterFormat(Image *img, int32 type, return 1; } +static uint8* +flipImage(Image *image) +{ + int i; + uint8 *newPx = (uint8*)rwMalloc(image->stride*image->height, 0); + for(i = 0; i < image->height; i++) + memcpy(&newPx[i*image->stride], &image->pixels[(image->height-1-i)*image->stride], image->stride); + return newPx; +} + bool32 rasterFromImage(Raster *raster, Image *image) { if((raster->type&0xF) != Raster::TEXTURE) return 0; +#ifdef RW_OPENGL // Unpalettize image if necessary but don't change original Image *truecolimg = nil; if(image->depth <= 8){ @@ -259,18 +270,28 @@ rasterFromImage(Raster *raster, Image *image) image = truecolimg; } + // NB: important to set the format of the input data here! Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); switch(image->depth){ case 32: if(raster->format != Raster::C8888 && raster->format != Raster::C888) goto err; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 1; break; case 24: if(raster->format != Raster::C888) goto err; + natras->format = GL_RGB; + natras->type = GL_UNSIGNED_BYTE; + natras->hasAlpha = 0; break; case 16: if(raster->format != Raster::C1555) goto err; + natras->format = GL_RGBA; + natras->type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + natras->hasAlpha = 1; break; case 8: @@ -283,12 +304,16 @@ rasterFromImage(Raster *raster, Image *image) natras->hasAlpha = image->hasAlpha(); -#ifdef RW_OPENGL + + uint8 *flipped = flipImage(image); + glBindTexture(GL_TEXTURE_2D, natras->texid); glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, raster->width, raster->height, - 0, natras->format, natras->type, image->pixels); + 0, natras->format, natras->type, flipped); glBindTexture(GL_TEXTURE_2D, 0); + + rwFree(flipped); #endif return 1; } diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index e5b2f1a..4d6039e 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -40,31 +40,29 @@ disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs) glDisableVertexAttribArray(a->index); } -void -lightingCB(bool32 normals) +int32 +lightingCB(Atomic *atomic) { - World *world; - RGBAf ambLight = { 0.0, 0.0, 0.0, 1.0 }; - int n = 0; + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; - world = (World*)engine->currentWorld; - // only unpositioned lights right now - FORLIST(lnk, world->globalLights){ - Light *l = Light::fromWorld(lnk); - if(normals && - l->getType() == Light::DIRECTIONAL && - l->getFlags() & Light::LIGHTATOMICS){ - if(n >= MAX_LIGHTS) - continue; - setLight(n++, l); - }else if(l->getType() == Light::AMBIENT){ - ambLight.red += l->color.red; - ambLight.green += l->color.green; - ambLight.blue += l->color.blue; + if(atomic->geometry->flags & rw::Geometry::LIGHT){ + ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData); + if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){ + // Get rid of lights that need normals when we don't have any + lightData.numDirectionals = 0; + lightData.numLocals = 0; } + return setLights(&lightData); + }else{ + memset(&lightData, 0, sizeof(lightData)); + return setLights(&lightData); } - setNumLights(n); - setAmbientLight(&ambLight); } #define U(i) currentShader->uniformLocations[i] @@ -77,7 +75,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) GLfloat surfProps[4]; setWorldMatrix(atomic->getFrame()->getLTM()); - lightingCB(!!(atomic->geometry->flags & Geometry::NORMALS)); + lightingCB(atomic); glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); @@ -86,7 +84,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; - simpleShader->use(); + defaultShader->use(); while(n--){ m = inst->material; @@ -98,7 +96,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) surfProps[1] = m->surfaceProps.specular; surfProps[2] = m->surfaceProps.diffuse; surfProps[3] = 0.0f; - glUniform4fv(U(u_surfaceProps), 1, surfProps); + glUniform4fv(U(u_surfProps), 1, surfProps); setTexture(0, m->texture); diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index 19dfc34..a3bd08f 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -16,6 +16,8 @@ namespace rw { namespace gl3 { +#include "shaders/header_vs.inc" + UniformRegistry uniformRegistry; int32 @@ -89,14 +91,17 @@ loadfile(const char *path) } static int -compileshader(GLenum type, const char *src, GLuint *shader) +compileshader(GLenum type, const char **src, GLuint *shader) { + GLint n; GLint shdr, success; GLint len; char *log; + for(n = 0; src[n]; n++); + shdr = glCreateShader(type); - glShaderSource(shdr, 1, &src, nil); + glShaderSource(shdr, n, src, nil); glCompileShader(shdr); glGetShaderiv(shdr, GL_COMPILE_STATUS, &success); if(!success){ @@ -139,6 +144,58 @@ linkprogram(GLint vs, GLint fs, GLuint *program) return 0; } +Shader* +Shader::create(const char **vsrc, const char **fsrc) +{ + GLuint vs, fs, program; + int i; + int fail; + + fail = compileshader(GL_VERTEX_SHADER, vsrc, &vs); + if(fail) + return nil; + + fail = compileshader(GL_FRAGMENT_SHADER, fsrc, &fs); + if(fail) + return nil; + + fail = linkprogram(vs, fs, &program); + if(fail) + return nil; + glDeleteProgram(vs); + glDeleteProgram(fs); + + Shader *sh = rwNewT(Shader, 1, MEMDUR_EVENT | ID_DRIVER); // or global? + + // set uniform block binding + for(i = 0; i < uniformRegistry.numBlocks; i++){ + int idx = glGetUniformBlockIndex(program, + uniformRegistry.blockNames[i]); + if(idx >= 0) + glUniformBlockBinding(program, idx, i); + } + + // query uniform locations + sh->program = program; + sh->uniformLocations = rwNewT(GLint, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER); + for(i = 0; i < uniformRegistry.numUniforms; i++) + sh->uniformLocations[i] = glGetUniformLocation(program, + uniformRegistry.uniformNames[i]); + + // set samplers + glUseProgram(program); + char name[64]; + GLint loc; + for(i = 0; i < 4; i++){ + sprintf(name, "tex%d", i); + loc = glGetUniformLocation(program, name); + glUniform1i(loc, i); + } + + return sh; +} + +#if 0 Shader* Shader::fromStrings(const char *vsrc, const char *fsrc) { @@ -191,6 +248,7 @@ Shader::fromFiles(const char *vspath, const char *fspath) rwFree(fsrc); return s; } +#endif void Shader::use(void) diff --git a/src/gl/gl3skin.cpp b/src/gl/gl3skin.cpp index 30b0aae..2169781 100644 --- a/src/gl/gl3skin.cpp +++ b/src/gl/gl3skin.cpp @@ -35,10 +35,15 @@ static void* skinOpen(void *o, int32, int32) { u_boneMatrices = registerUniform("u_boneMatrices"); + skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); + #include "shaders/simple_fs_gl3.inc" #include "shaders/skin_gl3.inc" - skinGlobals.pipelines[PLATFORM_GL3] = makeSkinPipeline(); - skinShader = Shader::fromStrings(skin_vert_src, simple_frag_src); + const char *vs[] = { header_vert_src, skin_vert_src, nil }; + const char *fs[] = { simple_frag_src, nil }; + skinShader = Shader::create(vs, fs); + assert(skinShader); + return o; } @@ -216,23 +221,34 @@ skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) static float skinMatrices[64*16]; void -updateSkinMatrices(Atomic *a) +uploadSkinMatrices(Atomic *a) { + int i; Skin *skin = Skin::get(a->geometry); HAnimHierarchy *hier = Skin::getHierarchy(a); Matrix *invMats = (Matrix*)skin->inverseMatrices; + Matrix tmp; - float *m; - m = (float*)skinMatrices; - for(int i = 0; i < hier->numNodes; i++){ - invMats[i].flags = 0; - Matrix::mult((Matrix*)m, &invMats[i], &hier->matrices[i]); - m[3] = 0.0f; - m[7] = 0.0f; - m[11] = 0.0f; - m[15] = 1.0f; - m += 16; + Matrix *m = (Matrix*)skinMatrices; + + if(hier->flags & HAnimHierarchy::LOCALSPACEMATRICES){ + for(i = 0; i < hier->numNodes; i++){ + invMats[i].flags = 0; + Matrix::mult(m, &invMats[i], &hier->matrices[i]); + m++; + } + }else{ + Matrix invAtmMat; + Matrix::invert(&invAtmMat, a->getFrame()->getLTM()); + for(i = 0; i < hier->numNodes; i++){ + invMats[i].flags = 0; + Matrix::mult(&tmp, &hier->matrices[i], &invAtmMat); + Matrix::mult(m, &invMats[i], &tmp); + m++; + } } + glUniformMatrix4fv(U(u_boneMatrices), 64, GL_FALSE, + (GLfloat*)skinMatrices); } void @@ -243,7 +259,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) GLfloat surfProps[4]; setWorldMatrix(atomic->getFrame()->getLTM()); - lightingCB(!!(atomic->geometry->flags & Geometry::NORMALS)); + lightingCB(atomic); glBindBuffer(GL_ARRAY_BUFFER, header->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo); @@ -252,14 +268,9 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) InstanceData *inst = header->inst; int32 n = header->numMeshes; -// rw::setRenderState(ALPHATESTFUNC, 1); -// rw::setRenderState(ALPHATESTREF, 50); - skinShader->use(); - updateSkinMatrices(atomic); - glUniformMatrix4fv(U(u_boneMatrices), 64, GL_FALSE, - (GLfloat*)skinMatrices); + uploadSkinMatrices(atomic); while(n--){ m = inst->material; @@ -271,7 +282,7 @@ skinRenderCB(Atomic *atomic, InstanceDataHeader *header) surfProps[1] = m->surfaceProps.specular; surfProps[2] = m->surfaceProps.diffuse; surfProps[3] = 0.0f; - glUniform4fv(U(u_surfaceProps), 1, surfProps); + glUniform4fv(U(u_surfProps), 1, surfProps); setTexture(0, m->texture); diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 09772d7..91e462c 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -57,7 +57,7 @@ enum AttribIndices // default uniform indices extern int32 u_matColor; -extern int32 u_surfaceProps; +extern int32 u_surfProps; struct InstanceData { @@ -92,7 +92,7 @@ struct InstanceDataHeader : rw::InstanceDataHeader struct Shader; -extern Shader *simpleShader; +extern Shader *defaultShader; struct Im3DVertex { @@ -146,15 +146,27 @@ void disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs); // Render state +// Vertex shader bits +enum +{ + // These should be low so they could be used as indices + VSLIGHT_DIRECT = 1, + VSLIGHT_POINT = 2, + VSLIGHT_SPOT = 4, + VSLIGHT_MASK = 7, // all the above + // less critical + VSLIGHT_AMBIENT = 8, +}; + +extern const char *header_vert_src; + // per Scene void setProjectionMatrix(float32*); void setViewMatrix(float32*); // per Object void setWorldMatrix(Matrix*); -void setAmbientLight(RGBAf*); -void setNumLights(int32 n); -void setLight(int32 n, Light*); +int32 setLights(WorldLights *lightData); // per Mesh void setTexture(int32 n, Texture *tex); @@ -176,7 +188,7 @@ public: void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); -void lightingCB(bool32 normals); +int32 lightingCB(Atomic *atomic); ObjPipeline *makeDefaultPipeline(void); diff --git a/src/gl/rwgl3shader.h b/src/gl/rwgl3shader.h index c209d58..72f736f 100644 --- a/src/gl/rwgl3shader.h +++ b/src/gl/rwgl3shader.h @@ -31,8 +31,9 @@ struct Shader // same number of elements as UniformRegistry::numUniforms GLint *uniformLocations; - static Shader *fromFiles(const char *vs, const char *fs); - static Shader *fromStrings(const char *vsrc, const char *fsrc); + static Shader *create(const char **vsrc, const char **fsrc); +// static Shader *fromFiles(const char *vs, const char *fs); +// static Shader *fromStrings(const char *vsrc, const char *fsrc); void use(void); void destroy(void); }; diff --git a/src/gl/shaders/Makefile b/src/gl/shaders/Makefile index ecb2e5b..cec56d3 100644 --- a/src/gl/shaders/Makefile +++ b/src/gl/shaders/Makefile @@ -1,4 +1,9 @@ -all: im2d_gl3.inc im3d_gl3.inc simple_vs_gl3.inc simple_fs_gl3.inc matfx_gl3.inc skin_gl3.inc +all: header_vs.inc im2d_gl3.inc im3d_gl3.inc default_vs_gl3.inc simple_fs_gl3.inc matfx_gl3.inc skin_gl3.inc + +header_vs.inc: header.vert + (echo 'const char *header_vert_src =';\ + sed 's/..*/"&\\n"/' header.vert;\ + echo ';') >header_vs.inc im2d_gl3.inc: im2d.vert (echo 'const char *im2d_vert_src =';\ @@ -10,10 +15,10 @@ im3d_gl3.inc: im3d.vert sed 's/..*/"&\\n"/' im3d.vert;\ echo ';') >im3d_gl3.inc -simple_vs_gl3.inc: simple.vert - (echo 'const char *simple_vert_src =';\ - sed 's/..*/"&\\n"/' simple.vert;\ - echo ';') >simple_vs_gl3.inc +default_vs_gl3.inc: default.vert + (echo 'const char *default_vert_src =';\ + sed 's/..*/"&\\n"/' default.vert;\ + echo ';') >default_vs_gl3.inc simple_fs_gl3.inc: simple.frag (echo 'const char *simple_frag_src =';\ diff --git a/src/gl/shaders/default.vert b/src/gl/shaders/default.vert new file mode 100644 index 0000000..cebf153 --- /dev/null +++ b/src/gl/shaders/default.vert @@ -0,0 +1,48 @@ +layout(location = 0) in vec3 in_pos; +layout(location = 1) in vec3 in_normal; +layout(location = 2) in vec4 in_color; +layout(location = 3) in vec2 in_tex0; + +out vec4 v_color; +out vec2 v_tex0; +out float v_fog; + +void +main(void) +{ + vec4 V = u_world * vec4(in_pos, 1.0); + gl_Position = u_proj * u_view * V; + vec3 N = mat3(u_world) * in_normal; + + v_tex0 = in_tex0; + + v_color = in_color; + v_color.rgb += u_ambLight.rgb*surfAmbient; + +#ifdef DIRECTIONALS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_directLights[i].enabled == 0.0) + break; + v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse; + } +#endif +#ifdef POINTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_pointLights[i].enabled == 0.0) + break; + v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse; + } +#endif +#ifdef SPOTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_spotLights[i].enabled == 0.0) + break; + v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse; + } +#endif + + v_color = clamp(v_color, 0.0f, 1.0); + v_color *= u_matColor; + + v_fog = DoFog(gl_Position.w); +} diff --git a/src/gl/shaders/default_vs_gl3.inc b/src/gl/shaders/default_vs_gl3.inc new file mode 100644 index 0000000..cc3965a --- /dev/null +++ b/src/gl/shaders/default_vs_gl3.inc @@ -0,0 +1,50 @@ +const char *default_vert_src = +"layout(location = 0) in vec3 in_pos;\n" +"layout(location = 1) in vec3 in_normal;\n" +"layout(location = 2) in vec4 in_color;\n" +"layout(location = 3) in vec2 in_tex0;\n" + +"out vec4 v_color;\n" +"out vec2 v_tex0;\n" +"out float v_fog;\n" + +"void\n" +"main(void)\n" +"{\n" +" vec4 V = u_world * vec4(in_pos, 1.0);\n" +" gl_Position = u_proj * u_view * V;\n" +" vec3 N = mat3(u_world) * in_normal;\n" + +" v_tex0 = in_tex0;\n" + +" v_color = in_color;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" + +"#ifdef DIRECTIONALS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_directLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse;\n" +" }\n" +"#endif\n" +"#ifdef POINTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_pointLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" +"#ifdef SPOTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_spotLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" + +" v_color = clamp(v_color, 0.0f, 1.0);\n" +" v_color *= u_matColor;\n" + +" v_fog = DoFog(gl_Position.w);\n" +"}\n" +; diff --git a/src/gl/shaders/header.vert b/src/gl/shaders/header.vert new file mode 100644 index 0000000..8048156 --- /dev/null +++ b/src/gl/shaders/header.vert @@ -0,0 +1,88 @@ +#version 330 + +layout(std140) uniform State +{ + int u_alphaTest; + float u_alphaRef; + + float u_fogStart; + float u_fogEnd; + float u_fogRange; + float u_fogDisable; + vec4 u_fogColor; +}; + +layout(std140) uniform Scene +{ + mat4 u_proj; + mat4 u_view; +}; + +#define MAX_LIGHTS 8 +struct Light { + float enabled; + float radius; + float minusCosAngle; + float hardSpot; + vec4 position; + vec4 direction; + vec4 color; +}; + +layout(std140) uniform Object +{ + mat4 u_world; + vec4 u_ambLight; + Light u_directLights[MAX_LIGHTS]; + Light u_pointLights[MAX_LIGHTS]; + Light u_spotLights[MAX_LIGHTS]; +}; + +uniform vec4 u_matColor; +uniform vec4 u_surfProps; // amb, spec, diff, extra + +#define surfAmbient (u_surfProps.x) +#define surfSpecular (u_surfProps.y) +#define surfDiffuse (u_surfProps.z) + +vec3 DoDirLight(Light L, vec3 N) +{ + float l = max(0.0, dot(N, -L.direction.xyz)); + return l*L.color.rgb; +} + +vec3 DoPointLight(Light L, vec3 V, vec3 N) +{ + // As on PS2 + vec3 dir = V - L.position.xyz; + float dist = length(dir); + float atten = max(0.0, (1.0 - dist/L.radius)); + float l = max(0.0, dot(N, -normalize(dir))); + return l*L.color.rgb*atten; +} + +vec3 DoSpotLight(Light L, vec3 V, vec3 N) +{ + // As on PS2 + vec3 dir = V - L.position.xyz; + float dist = length(dir); + float atten = max(0.0, (1.0 - dist/L.radius)); + dir /= dist; + float l = max(0.0, dot(N, -dir)); + float pcos = dot(dir, L.direction.xyz); // cos to point + float ccos = -L.minusCosAngle; + float falloff = (pcos-ccos)/(1.0-ccos); + if(falloff < 0) // outside of cone + l = 0; + l *= max(falloff, L.hardSpot); + return l*L.color.xyz*atten; +} + +float DoFog(float w) +{ + return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0); +} + +#define DIRECTIONALS +//#define POINTLIGHTS +//#define SPOTLIGHTS \ No newline at end of file diff --git a/src/gl/shaders/header_vs.inc b/src/gl/shaders/header_vs.inc new file mode 100644 index 0000000..2f884dc --- /dev/null +++ b/src/gl/shaders/header_vs.inc @@ -0,0 +1,89 @@ +const char *header_vert_src = +"#version 330\n" + +"layout(std140) uniform State\n" +"{\n" +" int u_alphaTest;\n" +" float u_alphaRef;\n" + +" float u_fogStart;\n" +" float u_fogEnd;\n" +" float u_fogRange;\n" +" float u_fogDisable;\n" +" vec4 u_fogColor;\n" +"};\n" + +"layout(std140) uniform Scene\n" +"{\n" +" mat4 u_proj;\n" +" mat4 u_view;\n" +"};\n" + +"#define MAX_LIGHTS 8\n" +"struct Light {\n" +" float enabled;\n" +" float radius;\n" +" float minusCosAngle;\n" +" float hardSpot;\n" +" vec4 position;\n" +" vec4 direction;\n" +" vec4 color;\n" +"};\n" + +"layout(std140) uniform Object\n" +"{\n" +" mat4 u_world;\n" +" vec4 u_ambLight;\n" +" Light u_directLights[MAX_LIGHTS];\n" +" Light u_pointLights[MAX_LIGHTS];\n" +" Light u_spotLights[MAX_LIGHTS];\n" +"};\n" + +"uniform vec4 u_matColor;\n" +"uniform vec4 u_surfProps; // amb, spec, diff, extra\n" + +"#define surfAmbient (u_surfProps.x)\n" +"#define surfSpecular (u_surfProps.y)\n" +"#define surfDiffuse (u_surfProps.z)\n" + +"vec3 DoDirLight(Light L, vec3 N)\n" +"{\n" +" float l = max(0.0, dot(N, -L.direction.xyz));\n" +" return l*L.color.rgb;\n" +"}\n" + +"vec3 DoPointLight(Light L, vec3 V, vec3 N)\n" +"{\n" +" // As on PS2\n" +" vec3 dir = V - L.position.xyz;\n" +" float dist = length(dir);\n" +" float atten = max(0.0, (1.0 - dist/L.radius));\n" +" float l = max(0.0, dot(N, -normalize(dir)));\n" +" return l*L.color.rgb*atten;\n" +"}\n" + +"vec3 DoSpotLight(Light L, vec3 V, vec3 N)\n" +"{\n" +" // As on PS2\n" +" vec3 dir = V - L.position.xyz;\n" +" float dist = length(dir);\n" +" float atten = max(0.0, (1.0 - dist/L.radius));\n" +" dir /= dist;\n" +" float l = max(0.0, dot(N, -dir));\n" +" float pcos = dot(dir, L.direction.xyz); // cos to point\n" +" float ccos = -L.minusCosAngle;\n" +" float falloff = (pcos-ccos)/(1.0-ccos);\n" +" if(falloff < 0) // outside of cone\n" +" l = 0;\n" +" l *= max(falloff, L.hardSpot);\n" +" return l*L.color.xyz*atten;\n" +"}\n" + +"float DoFog(float w)\n" +"{\n" +" return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0);\n" +"}\n" + +"#define DIRECTIONALS\n" +"//#define POINTLIGHTS\n" +"//#define SPOTLIGHTS\n"; diff --git a/src/gl/shaders/im2d.vert b/src/gl/shaders/im2d.vert index 46c5c20..cff0870 100644 --- a/src/gl/shaders/im2d.vert +++ b/src/gl/shaders/im2d.vert @@ -1,16 +1,3 @@ -#version 330 - -layout(std140) uniform State -{ - int u_alphaTest; - float u_alphaRef; - - int u_fogEnable; - float u_fogStart; - float u_fogEnd; - vec4 u_fogColor; -}; - uniform vec4 u_xform; layout(location = 0) in vec4 in_pos; @@ -26,8 +13,8 @@ main(void) { gl_Position = in_pos; gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw; + v_fog = DoFog(gl_Position.z); gl_Position.xyz *= gl_Position.w; v_color = in_color; v_tex0 = in_tex0; - v_fog = clamp((gl_Position.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); } diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc index 11f2e80..3212919 100644 --- a/src/gl/shaders/im2d_gl3.inc +++ b/src/gl/shaders/im2d_gl3.inc @@ -1,17 +1,4 @@ const char *im2d_vert_src = -"#version 330\n" - -"layout(std140) uniform State\n" -"{\n" -" int u_alphaTest;\n" -" float u_alphaRef;\n" - -" int u_fogEnable;\n" -" float u_fogStart;\n" -" float u_fogEnd;\n" -" vec4 u_fogColor;\n" -"};\n" - "uniform vec4 u_xform;\n" "layout(location = 0) in vec4 in_pos;\n" @@ -27,9 +14,9 @@ const char *im2d_vert_src = "{\n" " gl_Position = in_pos;\n" " gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" +" v_fog = DoFog(gl_Position.z);\n" " gl_Position.xyz *= gl_Position.w;\n" " v_color = in_color;\n" " v_tex0 = in_tex0;\n" -" v_fog = clamp((gl_Position.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" "}\n" ; diff --git a/src/gl/shaders/im3d.vert b/src/gl/shaders/im3d.vert index 55091d6..0276370 100644 --- a/src/gl/shaders/im3d.vert +++ b/src/gl/shaders/im3d.vert @@ -1,27 +1,3 @@ -#version 330 - -layout(std140) uniform State -{ - int u_alphaTest; - float u_alphaRef; - - int u_fogEnable; - float u_fogStart; - float u_fogEnd; - vec4 u_fogColor; -}; - -layout(std140) uniform Scene -{ - mat4 u_proj; - mat4 u_view; -}; - -layout(std140) uniform Object -{ - mat4 u_world; -}; - layout(location = 0) in vec3 in_pos; layout(location = 2) in vec4 in_color; layout(location = 3) in vec2 in_tex0; @@ -38,5 +14,5 @@ main(void) gl_Position = u_proj * cV; v_color = in_color; v_tex0 = in_tex0; - v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); + v_fog = DoFog(gl_Position.w); } diff --git a/src/gl/shaders/im3d_gl3.inc b/src/gl/shaders/im3d_gl3.inc index 2c878c0..7459606 100644 --- a/src/gl/shaders/im3d_gl3.inc +++ b/src/gl/shaders/im3d_gl3.inc @@ -1,28 +1,4 @@ const char *im3d_vert_src = -"#version 330\n" - -"layout(std140) uniform State\n" -"{\n" -" int u_alphaTest;\n" -" float u_alphaRef;\n" - -" int u_fogEnable;\n" -" float u_fogStart;\n" -" float u_fogEnd;\n" -" vec4 u_fogColor;\n" -"};\n" - -"layout(std140) uniform Scene\n" -"{\n" -" mat4 u_proj;\n" -" mat4 u_view;\n" -"};\n" - -"layout(std140) uniform Object\n" -"{\n" -" mat4 u_world;\n" -"};\n" - "layout(location = 0) in vec3 in_pos;\n" "layout(location = 2) in vec4 in_color;\n" "layout(location = 3) in vec2 in_tex0;\n" @@ -35,10 +11,10 @@ const char *im3d_vert_src = "main(void)\n" "{\n" " vec4 V = u_world * vec4(in_pos, 1.0);\n" -" vec4 cV = u_view * V; \n" +" vec4 cV = u_view * V;\n" " gl_Position = u_proj * cV;\n" " v_color = in_color;\n" " v_tex0 = in_tex0;\n" -" v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" +" v_fog = DoFog(gl_Position.w);\n" "}\n" ; diff --git a/src/gl/shaders/matfx_env.frag b/src/gl/shaders/matfx_env.frag index ed90362..87ec846 100644 --- a/src/gl/shaders/matfx_env.frag +++ b/src/gl/shaders/matfx_env.frag @@ -4,20 +4,38 @@ layout(std140) uniform State { int u_alphaTest; float u_alphaRef; - // fog etc. + + float u_fogStart; + float u_fogEnd; + float u_fogRange; + float u_fogDisable; + vec4 u_fogColor; }; -uniform sampler2D tex; +uniform sampler2D tex0; +uniform sampler2D tex1; + +uniform float u_coefficient; in vec4 v_color; in vec2 v_tex0; +in vec2 v_tex1; +in float v_fog; out vec4 color; void main(void) { - color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); + vec4 pass1 = v_color; + vec4 envColor = pass1; // TODO: colorClamp + + pass1 *= texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); + vec4 pass2 = envColor*u_coefficient*texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)); + + color.rgb = pass1.rgb*pass1.a + pass2.rgb; + color.a = pass1.a; + switch(u_alphaTest){ default: case 0: break; @@ -31,4 +49,3 @@ main(void) break; } } - diff --git a/src/gl/shaders/matfx_env.vert b/src/gl/shaders/matfx_env.vert index d63ada2..40cf146 100644 --- a/src/gl/shaders/matfx_env.vert +++ b/src/gl/shaders/matfx_env.vert @@ -1,33 +1,4 @@ -#version 330 - -layout(std140) uniform Scene -{ - mat4 u_proj; - mat4 u_view; -}; - -#define MAX_LIGHTS 8 -struct Light { - vec4 position; - vec4 direction; - vec4 color; - float radius; - float minusCosAngle; -}; - -layout(std140) uniform Object -{ - mat4 u_world; - vec4 u_ambLight; - int u_numLights; - Light u_lights[MAX_LIGHTS]; -}; - -uniform vec4 u_matColor; -uniform vec4 u_surfaceProps; // amb, spec, diff, extra - uniform mat4 u_texMatrix; -uniform float u_coefficient; layout(location = 0) in vec3 in_pos; layout(location = 1) in vec3 in_normal; @@ -36,6 +7,8 @@ layout(location = 3) in vec2 in_tex0; out vec4 v_color; out vec2 v_tex0; +out vec2 v_tex1; +out float v_fog; void main(void) @@ -44,15 +17,36 @@ main(void) gl_Position = u_proj * u_view * V; vec3 N = mat3(u_world) * in_normal; + v_tex0 = in_tex0; + v_tex1 = (u_texMatrix * vec4(N, 1.0)).xy; + v_color = in_color; - for(int i = 0; i < u_numLights; i++){ - float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); - v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; + v_color.rgb += u_ambLight.rgb*surfAmbient; + +#ifdef DIRECTIONALS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_directLights[i].enabled == 0.0) + break; + v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse; } - v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; +#endif +#ifdef POINTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_pointLights[i].enabled == 0.0) + break; + v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse; + } +#endif +#ifdef SPOTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_spotLights[i].enabled == 0.0) + break; + v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse; + } +#endif + + v_color = clamp(v_color, 0.0f, 1.0); v_color *= u_matColor; - v_color *= u_coefficient; - vec3 cN = mat3(u_view) * in_normal; - v_tex0 = (u_texMatrix * vec4(cN, 1.0)).xy; + v_fog = DoFog(gl_Position.w); } diff --git a/src/gl/shaders/matfx_gl3.inc b/src/gl/shaders/matfx_gl3.inc index 8b65b64..ac351fa 100644 --- a/src/gl/shaders/matfx_gl3.inc +++ b/src/gl/shaders/matfx_gl3.inc @@ -1,34 +1,5 @@ const char *matfx_env_vert_src = -"#version 330\n" - -"layout(std140) uniform Scene\n" -"{\n" -" mat4 u_proj;\n" -" mat4 u_view;\n" -"};\n" - -"#define MAX_LIGHTS 8\n" -"struct Light {\n" -" vec4 position;\n" -" vec4 direction;\n" -" vec4 color;\n" -" float radius;\n" -" float minusCosAngle;\n" -"};\n" - -"layout(std140) uniform Object\n" -"{\n" -" mat4 u_world;\n" -" vec4 u_ambLight;\n" -" int u_numLights;\n" -" Light u_lights[MAX_LIGHTS];\n" -"};\n" - -"uniform vec4 u_matColor;\n" -"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" - "uniform mat4 u_texMatrix;\n" -"uniform float u_coefficient;\n" "layout(location = 0) in vec3 in_pos;\n" "layout(location = 1) in vec3 in_normal;\n" @@ -37,6 +8,8 @@ const char *matfx_env_vert_src = "out vec4 v_color;\n" "out vec2 v_tex0;\n" +"out vec2 v_tex1;\n" +"out float v_fog;\n" "void\n" "main(void)\n" @@ -45,17 +18,38 @@ const char *matfx_env_vert_src = " gl_Position = u_proj * u_view * V;\n" " vec3 N = mat3(u_world) * in_normal;\n" +" v_tex0 = in_tex0;\n" +" v_tex1 = (u_texMatrix * vec4(N, 1.0)).xy;\n" + " v_color = in_color;\n" -" for(int i = 0; i < u_numLights; i++){\n" -" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" -" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" + +"#ifdef DIRECTIONALS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_directLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse;\n" " }\n" -" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" +"#endif\n" +"#ifdef POINTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_pointLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" +"#ifdef SPOTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_spotLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" + +" v_color = clamp(v_color, 0.0f, 1.0);\n" " v_color *= u_matColor;\n" -" v_color *= u_coefficient;\n" -" vec3 cN = mat3(u_view) * in_normal;\n" -" v_tex0 = (u_texMatrix * vec4(cN, 1.0)).xy;\n" +" v_fog = DoFog(gl_Position.w);\n" "}\n" ; const char *matfx_env_frag_src = @@ -65,20 +59,38 @@ const char *matfx_env_frag_src = "{\n" " int u_alphaTest;\n" " float u_alphaRef;\n" -" // fog etc.\n" + +" float u_fogStart;\n" +" float u_fogEnd;\n" +" float u_fogRange;\n" +" float u_fogDisable;\n" +" vec4 u_fogColor;\n" "};\n" -"uniform sampler2D tex;\n" +"uniform sampler2D tex0;\n" +"uniform sampler2D tex1;\n" + +"uniform float u_coefficient;\n" "in vec4 v_color;\n" "in vec2 v_tex0;\n" +"in vec2 v_tex1;\n" +"in float v_fog;\n" "out vec4 color;\n" "void\n" "main(void)\n" "{\n" -" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" +" vec4 pass1 = v_color;\n" +" vec4 envColor = pass1; // TODO: colorClamp\n" + +" pass1 *= texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" vec4 pass2 = envColor*u_coefficient*texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n" + +" color.rgb = pass1.rgb*pass1.a + pass2.rgb;\n" +" color.a = pass1.a;\n" + " switch(u_alphaTest){\n" " default:\n" " case 0: break;\n" @@ -92,5 +104,4 @@ const char *matfx_env_frag_src = " break;\n" " }\n" "}\n" - ; diff --git a/src/gl/shaders/simple.frag b/src/gl/shaders/simple.frag index 770d62b..9be99ad 100644 --- a/src/gl/shaders/simple.frag +++ b/src/gl/shaders/simple.frag @@ -5,13 +5,14 @@ layout(std140) uniform State int u_alphaTest; float u_alphaRef; - int u_fogEnable; float u_fogStart; float u_fogEnd; + float u_fogRange; + float u_fogDisable; vec4 u_fogColor; }; -uniform sampler2D tex; +uniform sampler2D tex0; in vec4 v_color; in vec2 v_tex0; @@ -22,9 +23,8 @@ out vec4 color; void main(void) { - color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y)); - if(u_fogEnable != 0) - color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); + color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y)); + color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog); switch(u_alphaTest){ default: case 0: break; diff --git a/src/gl/shaders/simple.vert b/src/gl/shaders/simple.vert deleted file mode 100644 index 2cd7f1a..0000000 --- a/src/gl/shaders/simple.vert +++ /dev/null @@ -1,68 +0,0 @@ -#version 330 - -layout(std140) uniform State -{ - int u_alphaTest; - float u_alphaRef; - - int u_fogEnable; - float u_fogStart; - float u_fogEnd; - vec4 u_fogColor; -}; - -layout(std140) uniform Scene -{ - mat4 u_proj; - mat4 u_view; -}; - -#define MAX_LIGHTS 8 -struct Light { - vec4 position; - vec4 direction; - vec4 color; - float radius; - float minusCosAngle; -}; - -layout(std140) uniform Object -{ - mat4 u_world; - vec4 u_ambLight; - int u_numLights; - Light u_lights[MAX_LIGHTS]; -}; - -uniform vec4 u_matColor; -uniform vec4 u_surfaceProps; // amb, spec, diff, extra - -layout(location = 0) in vec3 in_pos; -layout(location = 1) in vec3 in_normal; -layout(location = 2) in vec4 in_color; -layout(location = 3) in vec2 in_tex0; - -out vec4 v_color; -out vec2 v_tex0; -out float v_fog; - -void -main(void) -{ - vec4 V = u_world * vec4(in_pos, 1.0); - vec4 cV = u_view * V; - gl_Position = u_proj * cV; - vec3 N = mat3(u_world) * in_normal; - - v_color = in_color; - for(int i = 0; i < u_numLights; i++){ - float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); - v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; - } - v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; - v_color *= u_matColor; - - v_tex0 = in_tex0; - - v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); -} diff --git a/src/gl/shaders/simple_fs_gl3.inc b/src/gl/shaders/simple_fs_gl3.inc index 6cf1d7f..74b4ec0 100644 --- a/src/gl/shaders/simple_fs_gl3.inc +++ b/src/gl/shaders/simple_fs_gl3.inc @@ -6,13 +6,14 @@ const char *simple_frag_src = " int u_alphaTest;\n" " float u_alphaRef;\n" -" int u_fogEnable;\n" " float u_fogStart;\n" " float u_fogEnd;\n" +" float u_fogRange;\n" +" float u_fogDisable;\n" " vec4 u_fogColor;\n" "};\n" -"uniform sampler2D tex;\n" +"uniform sampler2D tex0;\n" "in vec4 v_color;\n" "in vec2 v_tex0;\n" @@ -23,9 +24,8 @@ const char *simple_frag_src = "void\n" "main(void)\n" "{\n" -" color = v_color*texture(tex, vec2(v_tex0.x, v_tex0.y));\n" -" if(u_fogEnable != 0)\n" -" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" +" color = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n" +" color.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n" " switch(u_alphaTest){\n" " default:\n" " case 0: break;\n" diff --git a/src/gl/shaders/simple_vs_gl3.inc b/src/gl/shaders/simple_vs_gl3.inc deleted file mode 100644 index 5332b28..0000000 --- a/src/gl/shaders/simple_vs_gl3.inc +++ /dev/null @@ -1,72 +0,0 @@ -const char *simple_vert_src = -"#version 330\n" - -"layout(std140) uniform State\n" -"{\n" -" int u_alphaTest;\n" -" float u_alphaRef;\n" - -" int u_fogEnable;\n" -" float u_fogStart;\n" -" float u_fogEnd;\n" -" vec4 u_fogColor;\n" -"};\n" - -"layout(std140) uniform Scene\n" -"{\n" -" mat4 u_proj;\n" -" mat4 u_view;\n" -"};\n" - -"#define MAX_LIGHTS 8\n" -"struct Light {\n" -" vec4 position;\n" -" vec4 direction;\n" -" vec4 color;\n" -" float radius;\n" -" float minusCosAngle;\n" -"};\n" - -"layout(std140) uniform Object\n" -"{\n" -" mat4 u_world;\n" -" vec4 u_ambLight;\n" -" int u_numLights;\n" -" Light u_lights[MAX_LIGHTS];\n" -"};\n" - -"uniform vec4 u_matColor;\n" -"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" - -"layout(location = 0) in vec3 in_pos;\n" -"layout(location = 1) in vec3 in_normal;\n" -"layout(location = 2) in vec4 in_color;\n" -"layout(location = 3) in vec2 in_tex0;\n" - -"out vec4 v_color;\n" -"out vec2 v_tex0;\n" -"out float v_fog;\n" - -"void\n" -"main(void)\n" -"{\n" -" vec3 lightdir = vec3(1.0, 1.0, -1.0);\n" - -" vec4 V = u_world * vec4(in_pos, 1.0);\n" -" vec4 cV = u_view * V; \n" -" gl_Position = u_proj * cV;\n" -" vec3 N = mat3(u_world) * in_normal;\n" - -" v_color = in_color;\n" -" for(int i = 0; i < u_numLights; i++){\n" -" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" -" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" -" }\n" -" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" -" v_color *= u_matColor;\n" - -" v_tex0 = in_tex0;\n" - -" v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" -"}\n" -; diff --git a/src/gl/shaders/skin.vert b/src/gl/shaders/skin.vert index 8861561..1a90898 100644 --- a/src/gl/shaders/skin.vert +++ b/src/gl/shaders/skin.vert @@ -1,41 +1,4 @@ -#version 330 - -layout(std140) uniform State -{ - int u_alphaTest; - float u_alphaRef; - - int u_fogEnable; - float u_fogStart; - float u_fogEnd; - vec4 u_fogColor; -}; - -layout(std140) uniform Scene -{ - mat4 u_proj; - mat4 u_view; -}; - -#define MAX_LIGHTS 8 -struct Light { - vec4 position; - vec4 direction; - vec4 color; - float radius; - float minusCosAngle; -}; - -layout(std140) uniform Object -{ - mat4 u_world; - vec4 u_ambLight; - int u_numLights; - Light u_lights[MAX_LIGHTS]; -}; - -uniform vec4 u_matColor; -uniform vec4 u_surfaceProps; // amb, spec, diff, extra +uniform mat4 u_boneMatrices[64]; layout(location = 0) in vec3 in_pos; layout(location = 1) in vec3 in_normal; @@ -44,8 +7,6 @@ layout(location = 3) in vec2 in_tex0; layout(location = 11) in vec4 in_weights; layout(location = 12) in vec4 in_indices; -uniform mat4 u_boneMatrices[64]; - out vec4 v_color; out vec2 v_tex0; out float v_fog; @@ -53,26 +14,44 @@ out float v_fog; void main(void) { - mat4 m = u_boneMatrices[int(in_indices[0])] * in_weights[0]; - m += u_boneMatrices[int(in_indices[1])] * in_weights[1]; - m += u_boneMatrices[int(in_indices[2])] * in_weights[2]; - m += u_boneMatrices[int(in_indices[3])] * in_weights[3]; - mat4 world = u_world * m; + vec3 SkinVertex = vec3(0.0, 0.0, 0.0); + vec3 SkinNormal = vec3(0.0, 0.0, 0.0); + for(int i = 0; i < 4; i++){ + SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i]; + SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i]; + } - vec4 V = world * vec4(in_pos, 1.0); - vec4 cV = u_view * V; - gl_Position = u_proj * cV; - vec3 N = mat3(world) * in_normal; + vec4 V = u_world * vec4(SkinVertex, 1.0); + gl_Position = u_proj * u_view * V; + vec3 N = mat3(u_world) * SkinNormal; v_color = in_color; - for(int i = 0; i < u_numLights; i++){ - float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz))); - v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z; + v_color.rgb += u_ambLight.rgb*surfAmbient; + +#ifdef DIRECTIONALS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_directLights[i].enabled == 0.0) + break; + v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse; } - v_color.rgb += u_ambLight.rgb*u_surfaceProps.x; +#endif +#ifdef POINTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_pointLights[i].enabled == 0.0) + break; + v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse; + } +#endif +#ifdef SPOTLIGHTS + for(int i = 0; i < MAX_LIGHTS; i++){ + if(u_spotLights[i].enabled == 0.0) + break; + v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse; + } +#endif v_color *= u_matColor; v_tex0 = in_tex0; - v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0); + v_fog = DoFog(gl_Position.z); } diff --git a/src/gl/shaders/skin_gl3.inc b/src/gl/shaders/skin_gl3.inc index 4730087..0880a54 100644 --- a/src/gl/shaders/skin_gl3.inc +++ b/src/gl/shaders/skin_gl3.inc @@ -1,42 +1,5 @@ const char *skin_vert_src = -"#version 330\n" - -"layout(std140) uniform State\n" -"{\n" -" int u_alphaTest;\n" -" float u_alphaRef;\n" - -" int u_fogEnable;\n" -" float u_fogStart;\n" -" float u_fogEnd;\n" -" vec4 u_fogColor;\n" -"};\n" - -"layout(std140) uniform Scene\n" -"{\n" -" mat4 u_proj;\n" -" mat4 u_view;\n" -"};\n" - -"#define MAX_LIGHTS 8\n" -"struct Light {\n" -" vec4 position;\n" -" vec4 direction;\n" -" vec4 color;\n" -" float radius;\n" -" float minusCosAngle;\n" -"};\n" - -"layout(std140) uniform Object\n" -"{\n" -" mat4 u_world;\n" -" vec4 u_ambLight;\n" -" int u_numLights;\n" -" Light u_lights[MAX_LIGHTS];\n" -"};\n" - -"uniform vec4 u_matColor;\n" -"uniform vec4 u_surfaceProps; // amb, spec, diff, extra\n" +"uniform mat4 u_boneMatrices[64];\n" "layout(location = 0) in vec3 in_pos;\n" "layout(location = 1) in vec3 in_normal;\n" @@ -45,8 +8,6 @@ const char *skin_vert_src = "layout(location = 11) in vec4 in_weights;\n" "layout(location = 12) in vec4 in_indices;\n" -"uniform mat4 u_boneMatrices[64];\n" - "out vec4 v_color;\n" "out vec2 v_tex0;\n" "out float v_fog;\n" @@ -54,27 +15,45 @@ const char *skin_vert_src = "void\n" "main(void)\n" "{\n" -" mat4 m = u_boneMatrices[int(in_indices[0])] * in_weights[0];\n" -" m += u_boneMatrices[int(in_indices[1])] * in_weights[1];\n" -" m += u_boneMatrices[int(in_indices[2])] * in_weights[2];\n" -" m += u_boneMatrices[int(in_indices[3])] * in_weights[3];\n" -" mat4 world = u_world * m;\n" +" vec3 SkinVertex = vec3(0.0, 0.0, 0.0);\n" +" vec3 SkinNormal = vec3(0.0, 0.0, 0.0);\n" +" for(int i = 0; i < 4; i++){\n" +" SkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];\n" +" SkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];\n" +" }\n" -" vec4 V = world * vec4(in_pos, 1.0);\n" -" vec4 cV = u_view * V; \n" -" gl_Position = u_proj * cV;\n" -" vec3 N = mat3(world) * in_normal;\n" +" vec4 V = u_world * vec4(SkinVertex, 1.0);\n" +" gl_Position = u_proj * u_view * V;\n" +" vec3 N = mat3(u_world) * SkinNormal;\n" " v_color = in_color;\n" -" for(int i = 0; i < u_numLights; i++){\n" -" float L = max(0.0, dot(N, -normalize(u_lights[i].direction.xyz)));\n" -" v_color.rgb += u_lights[i].color.rgb*L*u_surfaceProps.z;\n" +" v_color.rgb += u_ambLight.rgb*surfAmbient;\n" + +"#ifdef DIRECTIONALS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_directLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoDirLight(u_directLights[i], N)*surfDiffuse;\n" " }\n" -" v_color.rgb += u_ambLight.rgb*u_surfaceProps.x;\n" +"#endif\n" +"#ifdef POINTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_pointLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoPointLight(u_pointLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" +"#ifdef SPOTLIGHTS\n" +" for(int i = 0; i < MAX_LIGHTS; i++){\n" +" if(u_spotLights[i].enabled == 0.0)\n" +" break;\n" +" v_color.rgb += DoSpotLight(u_spotLights[i], V.xyz, N)*surfDiffuse;\n" +" }\n" +"#endif\n" " v_color *= u_matColor;\n" " v_tex0 = in_tex0;\n" -" v_fog = clamp((cV.z - u_fogEnd)/(u_fogStart - u_fogEnd), 0.0, 1.0);\n" +" v_fog = DoFog(gl_Position.z);\n" "}\n" ; diff --git a/src/image.cpp b/src/image.cpp index 6a350a4..0e86730 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -21,7 +21,13 @@ namespace rw { int32 Image::numAllocated; -// TODO: full 16 bit support +// Image formats are as follows: +// 32 bit has 4 bytes: 8888 RGBA +// 24 bit has 3 bytes: 888 RGB +// 16 bit has 2 bytes: 1555 ARGB stored in platform native order (TODO?) +// palettes always have 4 bytes: r, g, b, a +// 8 bit has 1 byte: x +// 4 bit has 1 byte per two pixels: 0xLR, where L and R are the left and right pixel resp. Image* Image::create(int32 width, int32 height, int32 depth)