diff --git a/src/d3d/d3dimmed.cpp b/src/d3d/d3dimmed.cpp index 331434b..e0df9d9 100644 --- a/src/d3d/d3dimmed.cpp +++ b/src/d3d/d3dimmed.cpp @@ -236,8 +236,9 @@ static int32 num3DVertices; void openIm3D(void) { - D3DVERTEXELEMENT9 elements[4] = { + D3DVERTEXELEMENT9 elements[5] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, offsetof(Im3DVertex, normal), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, offsetof(Im3DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, { 0, offsetof(Im3DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() @@ -273,6 +274,10 @@ closeIm3D(void) im3dindbuf = nil; } +// settable by user - TOOD: make this less shit +RGBA im3dMaterialColor = { 255, 255, 255, 255 }; +SurfaceProperties im3dSurfaceProps = { 1.0f, 1.0f, 1.0f }; + void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) { @@ -284,9 +289,22 @@ im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) if((flags & im3d::VERTEXUV) == 0) SetRenderStatePtr(TEXTURERASTER, nil); - static RGBA white = { 255, 255, 255, 255 }; - static SurfaceProperties surfprops = { 0.0f, 0.0f, 0.0f }; - setMaterial(white, surfprops); + void *shader = default_amb_VS; + if(flags & im3d::LIGHTING){ + setMaterial(im3dMaterialColor, im3dSurfaceProps); + int32 vsBits = lightingCB_Shader(); + // Pick a shader + if((vsBits & VSLIGHT_MASK) == 0) + shader = default_amb_VS; + else if((vsBits & VSLIGHT_MASK) == VSLIGHT_DIRECT) + shader = default_amb_dir_VS; + else + shader = default_all_VS; + }else{ + static RGBA white = { 255, 255, 255, 255 }; + static SurfaceProperties surfprops = { 0.0f, 0.0f, 0.0f }; + setMaterial(white, surfprops); + } uint8 *lockedvertices = lockVertices(im3dvertbuf, 0, numVertices*sizeof(Im3DVertex), D3DLOCK_DISCARD); memcpy(lockedvertices, vertices, numVertices*sizeof(Im3DVertex)); @@ -295,7 +313,7 @@ im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) setStreamSource(0, im3dvertbuf, 0, sizeof(Im3DVertex)); setVertexDeclaration(im3ddecl); - setVertexShader(default_amb_VS); + setVertexShader(shader); num3DVertices = numVertices; } diff --git a/src/d3d/d3drender.cpp b/src/d3d/d3drender.cpp index 86b7edc..d135d87 100644 --- a/src/d3d/d3drender.cpp +++ b/src/d3d/d3drender.cpp @@ -357,11 +357,6 @@ lightingCB_Shader(Atomic *atomic) if(atomic->geometry->flags & rw::Geometry::LIGHT){ ((World*)engine->currentWorld)->enumerateLights(atomic, &lightData); setAmbient(lightData.ambient); - 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 uploadLights(&lightData); }else{ static const RGBAf black = { 0.0f, 0.0f, 0.0f, 0.0f }; @@ -371,6 +366,22 @@ lightingCB_Shader(Atomic *atomic) } } +int32 +lightingCB_Shader(void) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + ((World*)engine->currentWorld)->enumerateLights(&lightData); + setAmbient(lightData.ambient); + return uploadLights(&lightData); +} + static RawMatrix identityXform = { { 1.0f, 0.0f, 0.0f }, 0.0f, { 0.0f, 1.0f, 0.0f }, 0.0f, diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 4ce29be..cabfeff 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -42,12 +42,16 @@ void setD3dMaterial(D3DMATERIAL9 *mat9); struct Im3DVertex { V3d position; + V3d normal; // librw extension uint32 color; float32 u, v; void setX(float32 x) { this->position.x = x; } void setY(float32 y) { this->position.y = y; } void setZ(float32 z) { this->position.z = z; } + void setNormalX(float32 x) { this->normal.x = x; } + void setNormalY(float32 y) { this->normal.y = y; } + void setNormalZ(float32 z) { this->normal.z = z; } void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = COLOR_ARGB(a, r, g, b); } void setU(float32 u) { this->u = u; } void setV(float32 v) { this->v = v; } @@ -55,11 +59,16 @@ struct Im3DVertex float getX(void) { return this->position.x; } float getY(void) { return this->position.y; } float getZ(void) { return this->position.z; } + float getNormalX(void) { return this->normal.x; } + float getNormalY(void) { return this->normal.y; } + float getNormalZ(void) { return this->normal.z; } RGBA getColor(void) { return makeRGBA(this->color>>16 & 0xFF, this->color>>8 & 0xFF, this->color & 0xFF, this->color>>24 & 0xFF); } float getU(void) { return this->u; } float getV(void) { return this->v; } }; +extern RGBA im3dMaterialColor; +extern SurfaceProperties im3dSurfaceProps; struct Im2DVertex { @@ -386,6 +395,7 @@ enum void lightingCB_Fix(Atomic *atomic); int32 lightingCB_Shader(Atomic *atomic); +int32 lightingCB_Shader(void); // for VS void uploadMatrices(void); // no world transform void uploadMatrices(Matrix *worldMat); diff --git a/src/gl/gl3immed.cpp b/src/gl/gl3immed.cpp index 3b4aae4..b66b7e5 100644 --- a/src/gl/gl3immed.cpp +++ b/src/gl/gl3immed.cpp @@ -193,9 +193,11 @@ im2DRenderIndexedPrimitive(PrimitiveType primType, static Shader *im3dShader; -static AttribDesc im3dattribDesc[3] = { +static AttribDesc im3dattribDesc[4] = { { ATTRIB_POS, GL_FLOAT, GL_FALSE, 3, sizeof(Im3DVertex), 0 }, + { ATTRIB_NORMAL, GL_FLOAT, GL_FALSE, 3, + sizeof(Im3DVertex), offsetof(Im3DVertex, normal) }, { ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4, sizeof(Im3DVertex), offsetof(Im3DVertex, r) }, { ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2, @@ -228,7 +230,7 @@ openIm3D(void) #ifdef RW_GL_USE_VAOS glGenVertexArrays(1, &im3DVao); glBindVertexArray(im3DVao); - setAttribPointers(im3dattribDesc, 3); + setAttribPointers(im3dattribDesc, 4); #endif } @@ -244,6 +246,10 @@ closeIm3D(void) im3dShader = nil; } +// settable by user - TOOD: make this less shit +RGBA im3dMaterialColor = { 255, 255, 255, 255 }; +SurfaceProperties im3dSurfaceProps = { 1.0f, 1.0f, 1.0f }; + void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) { @@ -253,7 +259,12 @@ im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) world = &ident; } setWorldMatrix(world); - im3dShader->use(); + if(flags & im3d::LIGHTING){ + setMaterial(im3dMaterialColor, im3dSurfaceProps); + int32 vsBits = lightingCB(); + defaultShader_fullLight->use(); + }else + im3dShader->use(); if((flags & im3d::VERTEXUV) == 0) SetRenderStatePtr(TEXTURERASTER, nil); @@ -266,7 +277,7 @@ im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags) glBufferData(GL_ARRAY_BUFFER, STARTVERTICES*sizeof(Im3DVertex), nil, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im3DVertex), vertices); #ifndef RW_GL_USE_VAOS - setAttribPointers(im3dattribDesc, 3); + setAttribPointers(im3dattribDesc, 4); #endif num3DVertices = numVertices; } @@ -296,7 +307,7 @@ void im3DEnd(void) { #ifndef RW_GL_USE_VAOS - disableAttribPointers(im3dattribDesc, 3); + disableAttribPointers(im3dattribDesc, 4); #endif } diff --git a/src/gl/gl3render.cpp b/src/gl/gl3render.cpp index 4dd79ba..a02c5c0 100644 --- a/src/gl/gl3render.cpp +++ b/src/gl/gl3render.cpp @@ -121,20 +121,29 @@ lightingCB(Atomic *atomic) lightData.locals = locals; lightData.numLocals = 8; - if(atomic->geometry->flags & rw::Geometry::LIGHT){ + 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{ + else memset(&lightData, 0, sizeof(lightData)); - return setLights(&lightData); - } + return setLights(&lightData); } +int32 +lightingCB(void) +{ + WorldLights lightData; + Light *directionals[8]; + Light *locals[8]; + lightData.directionals = directionals; + lightData.numDirectionals = 8; + lightData.locals = locals; + lightData.numLocals = 8; + + ((World*)engine->currentWorld)->enumerateLights(&lightData); + return setLights(&lightData); +} + + void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header) { diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index 73c344e..f361dc8 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -45,6 +45,8 @@ registerUniform(const char *name, UniformType type, int32 num) { int i; i = findUniform(name); + if(type == UNIFORM_NA) + num = 0; if(i >= 0){ Uniform *u = &uniformRegistry.uniforms[i]; assert(u->type == type); diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index 4b138ac..3275679 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -103,12 +103,16 @@ extern Shader *defaultShader_fullLight, *defaultShader_fullLight_noAT; struct Im3DVertex { V3d position; + V3d normal; // librw extension uint8 r, g, b, a; float32 u, v; void setX(float32 x) { this->position.x = x; } void setY(float32 y) { this->position.y = y; } void setZ(float32 z) { this->position.z = z; } + void setNormalX(float32 x) { this->normal.x = x; } + void setNormalY(float32 y) { this->normal.y = y; } + void setNormalZ(float32 z) { this->normal.z = z; } void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->r = r; this->g = g; this->b = b; this->a = a; } void setU(float32 u) { this->u = u; } @@ -117,10 +121,15 @@ struct Im3DVertex float getX(void) { return this->position.x; } float getY(void) { return this->position.y; } float getZ(void) { return this->position.z; } + float getNormalX(void) { return this->normal.x; } + float getNormalY(void) { return this->normal.y; } + float getNormalZ(void) { return this->normal.z; } RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); } float getU(void) { return this->u; } float getV(void) { return this->v; } }; +extern RGBA im3dMaterialColor; +extern SurfaceProperties im3dSurfaceProps; struct Im2DVertex { @@ -221,6 +230,7 @@ void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinsta void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header); void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header); int32 lightingCB(Atomic *atomic); +int32 lightingCB(void); void drawInst_simple(InstanceDataHeader *header, InstanceData *inst); // Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer diff --git a/src/gl/shaders/im3d.vert b/src/gl/shaders/im3d.vert index 7088352..280b128 100644 --- a/src/gl/shaders/im3d.vert +++ b/src/gl/shaders/im3d.vert @@ -8,8 +8,7 @@ void main(void) { vec4 Vertex = u_world * vec4(in_pos, 1.0); - vec4 CamVertex = u_view * Vertex; - gl_Position = u_proj * CamVertex; + gl_Position = u_proj * u_view * Vertex; v_color = in_color; v_tex0 = in_tex0; v_fog = DoFog(gl_Position.w); diff --git a/src/gl/shaders/im3d_gl.inc b/src/gl/shaders/im3d_gl.inc index 389589b..40ec7a1 100644 --- a/src/gl/shaders/im3d_gl.inc +++ b/src/gl/shaders/im3d_gl.inc @@ -9,8 +9,7 @@ const char *im3d_vert_src = "main(void)\n" "{\n" " vec4 Vertex = u_world * vec4(in_pos, 1.0);\n" -" vec4 CamVertex = u_view * Vertex;\n" -" gl_Position = u_proj * CamVertex;\n" +" gl_Position = u_proj * u_view * Vertex;\n" " v_color = in_color;\n" " v_tex0 = in_tex0;\n" " v_fog = DoFog(gl_Position.w);\n" diff --git a/src/gl/shaders/simple.frag b/src/gl/shaders/simple.frag index 32b2afb..34c1e43 100644 --- a/src/gl/shaders/simple.frag +++ b/src/gl/shaders/simple.frag @@ -12,4 +12,3 @@ main(void) DoAlphaTest(color.a); FRAGCOLOR(color); } - diff --git a/src/rwobjects.h b/src/rwobjects.h index 5cd833f..96394c2 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -872,6 +872,7 @@ struct World void removeClump(Clump *clump); void render(void); void enumerateLights(Atomic *atomic, WorldLights *lightData); + void enumerateLights(WorldLights *lightData); }; struct TexDictionary diff --git a/src/rwrender.h b/src/rwrender.h index 200837a..49fe0c4 100644 --- a/src/rwrender.h +++ b/src/rwrender.h @@ -123,6 +123,7 @@ enum TransformFlags NOCLIP = 4, // don't frustum clip VERTEXXYZ = 8, // has position VERTEXRGBA = 16, // has color + LIGHTING = 32, // do lighting, assumes normals (librw extension) EVERYTHING = VERTEXUV|VERTEXXYZ|VERTEXRGBA }; diff --git a/src/world.cpp b/src/world.cpp index 6432b37..e80b8e3 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -195,4 +195,44 @@ World::enumerateLights(Atomic *atomic, WorldLights *lightData) } } +// Find all lights, for im3d lighting extension +// missing flags and bounding spheres so more primitive than above +void +World::enumerateLights(WorldLights *lightData) +{ + int32 maxDirectionals, maxLocals; + + maxDirectionals = lightData->numDirectionals; + maxLocals = lightData->numLocals; + + lightData->numDirectionals = 0; + lightData->numLocals = 0; + lightData->numAmbients = 0; + lightData->ambient.red = 0.0f; + lightData->ambient.green = 0.0f; + lightData->ambient.blue = 0.0f; + lightData->ambient.alpha = 1.0f; + + FORLIST(lnk, this->globalLights){ + Light *l = Light::fromWorld(lnk); + if(l->getType() == Light::AMBIENT){ + lightData->ambient.red += l->color.red; + lightData->ambient.green += l->color.green; + lightData->ambient.blue += l->color.blue; + lightData->numAmbients++; + }else if(l->getType() == Light::DIRECTIONAL){ + if(lightData->numDirectionals < maxDirectionals) + lightData->directionals[lightData->numDirectionals++] = l; + } + } + + FORLIST(lnk, this->localLights){ + if(lightData->numLocals >= maxLocals) + return; + + Light *l = Light::fromWorld(lnk); + lightData->locals[lightData->numLocals++] = l; + } +} + }