dhewm / dhewm3

dhewm 3 main repository
https://dhewm3.org/
GNU General Public License v3.0
1.74k stars 340 forks source link

GLSL backend #15

Open dhewg opened 11 years ago

dhewg commented 11 years ago

There're two GLSL branches floating around: 1) https://git.iodoom.org/~raynorpat/iodoom3/raynorpats-glsl_iodoom3/commits/master and a continuation 2) https://github.com/LogicalError/doom3.gpl/commits/master

Both are based on different trees, and I merged those a while back on top of my tree: http://static.hackmii.com/dhewg/0001-Add-GLSL-backend.patch

My lack of GL foo is disturbing, but maybe someone wants to finish this backend?

andre-d commented 11 years ago

I would like to do it next time I have time, might pick it up this evening.

andre-d commented 11 years ago

Any idea whats not working/not finished in it? I played with it and it seemed to work just fine.

andre-d commented 11 years ago

Alright, I have identified some differences/flaws which I want to correct. (I first updated to his latest versions of the shaders your patches were missing)

1) Specularity looks sketchy compared to arb2

3) Optimize, optimize, optimize

4) Custom render passes

5) Hook up with a high resolution timer to tell how long renders are taking

andre-d commented 11 years ago

Btw the commit is at 2bfe28dcb2c2c00732d03d50a523023e6b55428d (With the modifications)

scaronni commented 11 years ago

Here's a newly released branch with both GLSL and ES 2.0 renderer:

https://github.com/omcfadde/idtech4/commits/es2

omcfadde commented 11 years ago

FYI, my tree has been renamed and moved to https://github.com/omcfadde/dante

GLSL backend is implemented with some minor missing features (i.e. shaders for heatHaze, heatHazeWithMask, etc.) There may also be other bugs. Hopefully I will have time to fix them soon.

tapir commented 11 years ago

Is there someone working on merging dante's modifications?

motorsep commented 11 years ago

Not that I know of. Plus what's there to merge? It's not 100% working yet.

andre-d commented 11 years ago

heathaze and multitexture and such will need to be implemented for that to happen

motorsep commented 11 years ago

Why does one need GLSL backend precisely ? ARB shaders can be made using RenderMonkey and FX Composer afaik. Where it's ARB or GLSL, one still needs to know what to do and how to do it.

andre-d commented 11 years ago

ARB is outdated and basically coding assembly, GLSL is more like coding C.

motorsep commented 11 years ago

Oh, I am aware of that. But isn't it irrelevant when using above mentioned tools for share creation ?

andre-d commented 11 years ago

Even if you use some kind of shader compiler to compile down to ARB, arb is still limited in terms of available features/limits. FX Composer can be used to create CG shaders, which can then be compiled down into ARB only if you use the feature sets available in ARB. GLSL is the more modern solution, even if some shader languages compile down to ARB still...and even then..you are coding in CG..not GLSL..two totally separate shader languages.

omcfadde commented 11 years ago

It's possible for the GLSL compiler to generate much more efficient code for whichever hardware you happen to be running. While both ARB programs and GLSL shaders may be compiled to the same intermediate representation internally, GLSL is able to provide a significantly more context information which the compiler can use to generate more efficient code.

Many so called high-level optimizations that are possible when compiling from GLSL are simply not possible, or are prohibitively difficult with lower level languages (or intermediate representations thereof.)

You are comparing apples and oranges when talking about GLSL shaders vs. ARB fragment and vertex programs, and I generally do not like the "C vs. assembly" comparison, but in this case the example is quite apt; the C compiler will eventually use the assembler, but not before it's had a chance to make many optimization passes at the high level. The assembler may then perform further low-level optimization on the IR before finally emitting machine code.

andre-d, heat haze will be coming; I have some work on a local branch, but it's not release ready yet.

nbohr1more commented 10 years ago

RaynorPat has a new branch with Mh's VBO Cache and GLSL ported from BFG:

https://github.com/raynorpat/morpheus

motorsep commented 8 years ago

Did you see that his fork is no longer on Github ?

nbohr1more commented 8 years ago

This one is:

https://github.com/raynorpat/Doom3

however, it seems that he also has a deferred shading branch

https://github.com/raynorpat/dhewm3

too.

DanielGibson commented 5 years ago

Just a note here: if this (or any other new rendering-backend) is gonna happen eventually, I'd like

coreyoconnor commented 5 years ago

@DanielGibson the second point: translation of ARB to GLSL is an interesting problem on it's own. Are you aware of any existing tooling that does this?

I searched for a bit and only found people asking the same.

DanielGibson commented 5 years ago

I'm not, but it doesn't seem like a super hard problem to me? ARB assembly seems to be pretty limited (even more so when assuming that the relevant shaders only use the core instructions and not nvidias extensions), it'd probably be possible to just translate it line by line to equivalent GLSL (and then add some "static", most probably game-specific, GLSL code before and possibly after that for passing in/out vertex data and uniforms).

One problem seems to be that finding documentation and tutorials/examples on ARB assembly is kinda hard; here are a few sources I found when researching this a while ago though:

Despite doing this (minimal) research I haven't looked into how to actually do this though, so if you or someone else wants to do it, that'd be great! :-) Probably a good starting point on the C++ side of things is an existing "modern" OpenGL renderer that uses GLSL (with rewritten shaders), I'd probably use the one from D3Wasm (https://github.com/gabrielcuvillier/d3wasm).

motorsep commented 5 years ago

Thread with beard... @coreyoconnor Why not to just use renderer from Doom 3 BFG for dhewm3 ?

raynorpat commented 5 years ago

@motorsep that doesn't really bring the compatibility piece for mods still using custom ARB shaders

motorsep commented 5 years ago

@motorsep that doesn't really bring the compatibility piece for mods still using custom ARB shaders

What if someone writes a parser to convert ARB to GLSL on the fly? :)

coreyoconnor commented 5 years ago

@motorsep

Interesting project right? A C++ library providing source to source translation of ARB to GLSL. Would be useful outside of doom 3 as well I bet.

turol commented 5 years ago

The specs for ARB_vertex_program and ARB_fragment_program contain a grammar of the language.

revelator commented 4 years ago

If you can live with only the interaction shader being drawn with GLSL this might interrest you.

```c++ /* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "precompiled.h" #include "tr_local.h" /* =========================================================================== DEFAULT GLSL SHADER =========================================================================== */ #define GLSL_VERSION_ATTRIBS \ "#version 130\n" #define GLSL_INPUT_ATTRIBS \ "in vec4 attrTexCoords;\n" \ "in vec3 attrTangents0;\n" \ "in vec3 attrTangents1;\n" \ "in vec3 attrNormal;\n" \ "mat3x3 u_lightMatrix = mat3x3 (attrTangents0, attrTangents1, attrNormal);\n\n" #define GLSL_UNIFORMS \ "uniform vec4 u_light_origin;\n" \ "uniform vec4 u_view_origin;\n" \ "uniform vec4 u_color_modulate;\n" \ "uniform vec4 u_color_add;\n" \ "uniform mat2x4 u_diffMatrix;\n" \ "uniform mat2x4 u_bumpMatrix;\n" \ "uniform mat2x4 u_specMatrix;\n" \ "uniform mat4x4 u_projMatrix;\n" \ "uniform mat4x4 u_fallMatrix;\n" \ "uniform sampler2D bumpImage;\n" \ "uniform sampler2D lightFalloffImage;\n" \ "uniform sampler2D lightProjectImage;\n" \ "uniform sampler2D diffuseImage;\n" \ "uniform sampler2D specularImage;\n" \ "uniform vec4 u_constant_diffuse;\n" \ "uniform vec4 u_constant_specular;\n\n" #define GLSL_VARYINGS \ "varying vec2 diffCoords;\n" \ "varying vec2 bumpCoords;\n" \ "varying vec2 specCoords;\n" \ "varying vec4 projCoords;\n" \ "varying vec4 fallCoords;\n" \ "varying vec3 lightDir;\n" \ "varying vec3 halfAngle;\n" \ "varying vec4 Color;\n" // these are our GLSL interaction shaders #define interaction_vs \ GLSL_VERSION_ATTRIBS \ GLSL_INPUT_ATTRIBS \ GLSL_UNIFORMS \ GLSL_VARYINGS \ "void main ()\n" \ "{\n" \ " // we must use ftransform as Doom 3 needs invariant position\n" \ " gl_Position = ftransform ();\n" \ "\n" \ " diffCoords = attrTexCoords * u_diffMatrix;\n" \ " bumpCoords = attrTexCoords * u_bumpMatrix;\n" \ " specCoords = attrTexCoords * u_specMatrix;\n" \ "\n" \ " projCoords = gl_Vertex * u_projMatrix;\n" \ " fallCoords = gl_Vertex * u_fallMatrix;\n" \ "\n" \ " Color = (gl_Color * u_color_modulate) + u_color_add;\n" \ "\n" \ " vec3 OffsetViewOrigin = (u_view_origin - gl_Vertex).xyz;\n" \ " vec3 OffsetLightOrigin = (u_light_origin - gl_Vertex).xyz;\n" \ "\n" \ " lightDir = OffsetLightOrigin * u_lightMatrix;\n" \ " halfAngle = (normalize (OffsetViewOrigin) + normalize (OffsetLightOrigin)) * u_lightMatrix;\n" \ "}\n\n" #define interaction_fs \ GLSL_VERSION_ATTRIBS \ GLSL_UNIFORMS \ GLSL_VARYINGS \ "void main ()\n" \ "{\n" \ " vec3 normalMap = texture2D (bumpImage, bumpCoords).agb * 2.0 - 1.0;\n" \ " vec4 lightMap = texture2DProj (lightProjectImage, projCoords);\n" \ "\n" \ " lightMap *= dot (normalize (lightDir), normalMap);\n" \ " lightMap *= texture2DProj (lightFalloffImage, fallCoords);\n" \ " lightMap *= Color;\n" \ "\n" \ " vec4 diffuseMap = texture2D (diffuseImage, diffCoords) * u_constant_diffuse;\n" \ " float specularComponent = clamp ((dot (normalize (halfAngle), normalMap) - 0.75) * 4.0, 0.0, 1.0);\n" \ "\n" \ " vec4 specularResult = u_constant_specular * (specularComponent * specularComponent);\n" \ " vec4 specularMap = texture2D (specularImage, specCoords) * 2.0;\n" \ "\n" \ " gl_FragColor = (diffuseMap + (specularResult * specularMap)) * lightMap;\n" \ "}\n\n" /* 32 bit hexadecimal 0, BFG had this set to a negative value which is illegal on unsigned */ static const GLuint INVALID_PROGRAM = 0x00000000; static GLuint u_light_origin = INVALID_PROGRAM; static GLuint u_view_origin = INVALID_PROGRAM; static GLuint u_color_modulate = INVALID_PROGRAM; static GLuint u_color_add = INVALID_PROGRAM; static GLuint u_constant_diffuse = INVALID_PROGRAM; static GLuint u_constant_specular = INVALID_PROGRAM; static GLuint u_diffMatrix = INVALID_PROGRAM; static GLuint u_bumpMatrix = INVALID_PROGRAM; static GLuint u_specMatrix = INVALID_PROGRAM; static GLuint u_projMatrix = INVALID_PROGRAM; static GLuint u_fallMatrix = INVALID_PROGRAM; static GLuint rb_glsl_interaction_program = INVALID_PROGRAM; /* ================== RB_GLSL_MakeMatrix ================== */ static float *RB_GLSL_MakeMatrix( const float *in1 = 0, const float *in2 = 0, const float *in3 = 0, const float *in4 = 0 ) { static float m[16]; if( in1 ) { SIMDProcessor->Memcpy( &m[0], in1, sizeof( float ) * 4 ); } if( in2 ) { SIMDProcessor->Memcpy( &m[4], in2, sizeof( float ) * 4 ); } if( in3 ) { SIMDProcessor->Memcpy( &m[8], in3, sizeof( float ) * 4 ); } if( in4 ) { SIMDProcessor->Memcpy( &m[12], in4, sizeof( float ) * 4 ); } return m; } /* Calculate matrix offsets */ #define DIFFMATRIX( ofs ) din->diffuseMatrix[ofs].ToFloatPtr () #define BUMPMATRIX( ofs ) din->bumpMatrix[ofs].ToFloatPtr () #define SPECMATRIX( ofs ) din->specularMatrix[ofs].ToFloatPtr () #define PROJMATRIX( ofs ) din->lightProjection[ofs].ToFloatPtr () /* ========================================================================================= GENERAL INTERACTION RENDERING ========================================================================================= */ /* ================== RB_ARB2_BindTexture ================== */ void RB_ARB2_BindTexture( int unit, idImage *tex ) { backEnd.glState.currenttmu = unit; glActiveTextureARB( GL_TEXTURE0_ARB + unit ); tex->BindFragment(); } /* ================== RB_ARB2_UnbindTexture ================== */ void RB_ARB2_UnbindTexture( int unit ) { backEnd.glState.currenttmu = unit; glActiveTextureARB( GL_TEXTURE0_ARB + unit ); globalImages->BindNull(); } /* ================== RB_ARB2_BindInteractionTextureSet ================== */ void RB_ARB2_BindInteractionTextureSet( const drawInteraction_t *din ) { // texture 1 will be the per-surface bump map RB_ARB2_BindTexture( 1, din->bumpImage ); // texture 2 will be the light falloff texture RB_ARB2_BindTexture( 2, din->lightFalloffImage ); // texture 3 will be the light projection texture RB_ARB2_BindTexture( 3, din->lightImage ); // texture 4 is the per-surface diffuse map RB_ARB2_BindTexture( 4, din->diffuseImage ); // texture 5 is the per-surface specular map RB_ARB2_BindTexture( 5, din->specularImage ); } /* ================== RB_GLSL_DrawInteraction ================== */ static void RB_GLSL_DrawInteraction( const drawInteraction_t *din ) { /* Half Lambertian constants */ static const float whalf[] = { 0.0f, 0.0f, 0.0f, 0.5f }; static const float wzero[] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const float wone[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // load all the vertex program parameters glUniform4fv( u_light_origin, 1, din->localLightOrigin.ToFloatPtr() ); glUniform4fv( u_view_origin, 1, din->localViewOrigin.ToFloatPtr() ); glUniformMatrix2x4fv( u_diffMatrix, 1, GL_FALSE, RB_GLSL_MakeMatrix( DIFFMATRIX( 0 ), DIFFMATRIX( 1 ) ) ); glUniformMatrix2x4fv( u_bumpMatrix, 1, GL_FALSE, RB_GLSL_MakeMatrix( BUMPMATRIX( 0 ), BUMPMATRIX( 1 ) ) ); glUniformMatrix2x4fv( u_specMatrix, 1, GL_FALSE, RB_GLSL_MakeMatrix( SPECMATRIX( 0 ), SPECMATRIX( 1 ) ) ); glUniformMatrix4fv( u_projMatrix, 1, GL_FALSE, RB_GLSL_MakeMatrix( PROJMATRIX( 0 ), PROJMATRIX( 1 ), wzero, PROJMATRIX( 2 ) ) ); glUniformMatrix4fv( u_fallMatrix, 1, GL_FALSE, RB_GLSL_MakeMatrix( PROJMATRIX( 3 ), whalf, wzero, wone ) ); /* Lambertian constants */ static const float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; static const float negOne[4] = { -1.0f, -1.0f, -1.0f, -1.0f }; switch( din->vertexColor ) { case SVC_IGNORE: glUniform4fv( u_color_modulate, 1, zero ); glUniform4fv( u_color_add, 1, one ); break; case SVC_MODULATE: glUniform4fv( u_color_modulate, 1, one ); glUniform4fv( u_color_add, 1, zero ); break; case SVC_INVERSE_MODULATE: glUniform4fv( u_color_modulate, 1, negOne ); glUniform4fv( u_color_add, 1, one ); break; } // set the constant colors glUniform4fv( u_constant_diffuse, 1, din->diffuseColor.ToFloatPtr() ); glUniform4fv( u_constant_specular, 1, din->specularColor.ToFloatPtr() ); // set the textures RB_ARB2_BindInteractionTextureSet( din ); // draw it RB_DrawElementsWithCounters( din->surf->geo ); } /* ================== RB_ARB2_DrawInteraction ================== */ void RB_ARB2_DrawInteraction( const drawInteraction_t *din ) { // load all the vertex program parameters glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, din->localLightOrigin.ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_VIEW_ORIGIN, din->localViewOrigin.ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_S, din->lightProjection[0].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_T, din->lightProjection[1].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_Q, din->lightProjection[2].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_FALLOFF_S, din->lightProjection[3].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_S, din->bumpMatrix[0].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_T, din->bumpMatrix[1].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_S, din->specularMatrix[0].ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->specularMatrix[1].ToFloatPtr() ); // testing fragment based normal mapping if( r_testARBProgram.GetBool() ) { glProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 2, din->localLightOrigin.ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 3, din->localViewOrigin.ToFloatPtr() ); } static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; static const float negOne[4] = { -1, -1, -1, -1 }; switch( din->vertexColor ) { case SVC_IGNORE: glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, zero ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one ); break; case SVC_MODULATE: glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, one ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, zero ); break; case SVC_INVERSE_MODULATE: glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, negOne ); glProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one ); break; } // set the constant colors glProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, din->diffuseColor.ToFloatPtr() ); glProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 1, din->specularColor.ToFloatPtr() ); // set the textures RB_ARB2_BindInteractionTextureSet( din ); // draw it RB_DrawElementsWithCounters( din->surf->geo ); } /* ============= RB_ARB2_SharedSurfaceSetup ============= */ void RB_ARB2_SharedSurfaceSetup( const drawSurf_t *surf ) { // set the vertex pointers idDrawVert *ac = ( idDrawVert * ) vertexCache.Position( surf->geo->ambientCache ); glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), ac->color ); glVertexAttribPointerARB( 11, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); glVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() ); glVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() ); glVertexAttribPointerARB( 8, 2, GL_FLOAT, false, sizeof( idDrawVert ), ac->st.ToFloatPtr() ); glVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); } /* ============= RB_ARB2_CreateDrawInteractions ============= */ void RB_ARB2_CreateDrawInteractions( const drawSurf_t *surf ) { if( !surf ) { return; } // perform setup here that will be constant for all interactions GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc ); // enable the vertex arrays glEnableVertexAttribArrayARB( 8 ); glEnableVertexAttribArrayARB( 9 ); glEnableVertexAttribArrayARB( 10 ); glEnableVertexAttribArrayARB( 11 ); glEnableClientState( GL_COLOR_ARRAY ); // check for enabled GLSL program first, if it fails go back to ARB if( rb_glsl_interaction_program != INVALID_PROGRAM ) { // enable GLSL programs glUseProgram( rb_glsl_interaction_program ); // texture 0 is the normalization cube map for the vector towards the light if( backEnd.vLight->lightShader->IsAmbientLight() ) { RB_ARB2_BindTexture( 0, globalImages->ambientNormalMap ); } else { RB_ARB2_BindTexture( 0, globalImages->normalCubeMapImage ); } // no test program in GLSL renderer RB_ARB2_BindTexture( 6, globalImages->specularTableImage ); for( /**/; surf; surf = surf->nextOnLight ) { // perform setup here that will not change over multiple interaction passes RB_ARB2_SharedSurfaceSetup( surf ); // this may cause RB_ARB2_DrawInteraction to be executed multiple // times with different colors and images if the surface or light have multiple layers RB_CreateSingleDrawInteractions( surf, RB_GLSL_DrawInteraction ); } // back to fixed (or ARB program) glUseProgram( INVALID_PROGRAM ); } else // Do it the old way { // enable ASM programs glEnable( GL_VERTEX_PROGRAM_ARB ); glEnable( GL_FRAGMENT_PROGRAM_ARB ); // texture 0 is the normalization cube map for the vector towards the light if( backEnd.vLight->lightShader->IsAmbientLight() ) { RB_ARB2_BindTexture( 0, globalImages->ambientNormalMap ); } else { RB_ARB2_BindTexture( 0, globalImages->normalCubeMapImage ); } // bind the vertex program if( r_testARBProgram.GetBool() ) { RB_ARB2_BindTexture( 6, globalImages->specular2DTableImage ); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_TEST ); glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST ); } else { RB_ARB2_BindTexture( 6, globalImages->specularTableImage ); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION ); glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION ); } for( /**/; surf; surf = surf->nextOnLight ) { // perform setup here that will not change over multiple interaction passes RB_ARB2_SharedSurfaceSetup( surf ); // this may cause RB_ARB2_DrawInteraction to be exacuted multiple // times with different colors and images if the surface or light have multiple layers RB_CreateSingleDrawInteractions( surf, RB_ARB2_DrawInteraction ); } // need to disable ASM programs again glBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_NONE ); glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, VPROG_NONE ); glDisable( GL_VERTEX_PROGRAM_ARB ); glDisable( GL_FRAGMENT_PROGRAM_ARB ); } // disable vertex arrays glDisableVertexAttribArrayARB( 8 ); glDisableVertexAttribArrayARB( 9 ); glDisableVertexAttribArrayARB( 10 ); glDisableVertexAttribArrayARB( 11 ); glDisableClientState( GL_COLOR_ARRAY ); // disable features RB_ARB2_UnbindTexture( 6 ); RB_ARB2_UnbindTexture( 5 ); RB_ARB2_UnbindTexture( 4 ); RB_ARB2_UnbindTexture( 3 ); RB_ARB2_UnbindTexture( 2 ); RB_ARB2_UnbindTexture( 1 ); backEnd.glState.currenttmu = -1; GL_SelectTexture( 0 ); } /* ================== RB_ARB2_InteractionPass ================== */ void RB_ARB2_InteractionPass( const drawSurf_t *shadowSurfs, const drawSurf_t *lightSurfs ) { // these are allway's enabled since we do not yet use GLSL shaders for the shadows. glEnable( GL_VERTEX_PROGRAM_ARB ); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW ); // save on state changes by not bothering to setup/takedown all the messy states when there are no surfs to draw if( shadowSurfs ) { RB_StencilShadowPass( shadowSurfs ); } if( lightSurfs ) { RB_ARB2_CreateDrawInteractions( lightSurfs ); } // need to disable ASM programs again, we do not check for GLSL here since we do not use it for shadows. glBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_NONE ); glDisable( GL_VERTEX_PROGRAM_ARB ); } /* ================== RB_ARB2_DrawInteractions ================== */ void RB_ARB2_DrawInteractions( void ) { viewLight_t *vLight; GL_SelectTexture( 0 ); // ensure that GLSL is down comming in here. glUseProgram( INVALID_PROGRAM ); // for each light, perform adding and shadowing for( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) { backEnd.vLight = vLight; // do fogging later if( vLight->lightShader->IsFogLight() ) { continue; } if( vLight->lightShader->IsBlendLight() ) { continue; } // nothing to see here; these aren't the surfaces you're looking for; move along if( !vLight->localInteractions && !vLight->globalInteractions && !vLight->translucentInteractions ) { continue; } // clear the stencil buffer if needed if( vLight->globalShadows || vLight->localShadows ) { backEnd.currentScissor = vLight->scissorRect; if( r_useScissor.GetBool() ) { glScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1, backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1, backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 ); } glClear( GL_STENCIL_BUFFER_BIT ); } else { // no shadows, so no need to read or write the stencil buffer // we might in theory want to use GL_ALWAYS instead of disabling // completely, to satisfy the invarience rules glStencilFunc( GL_ALWAYS, 128, 255 ); } // run our passes for global and local RB_ARB2_InteractionPass( vLight->globalShadows, vLight->localInteractions ); RB_ARB2_InteractionPass( vLight->localShadows, vLight->globalInteractions ); // translucent surfaces never get stencil shadowed if( r_skipTranslucent.GetBool() ) { continue; } glStencilFunc( GL_ALWAYS, 128, 255 ); backEnd.depthFunc = GLS_DEPTHFUNC_LESS; RB_ARB2_CreateDrawInteractions( vLight->translucentInteractions ); backEnd.depthFunc = GLS_DEPTHFUNC_EQUAL; } // disable stencil shadow test glStencilFunc( GL_ALWAYS, 128, 255 ); GL_SelectTexture( 0 ); } //=================================================================================== typedef struct { GLenum target; GLuint ident; char name[64]; } progDef_t; static const int MAX_GLPROGS = 256; // a single file can have both a vertex program and a fragment program // removed old invalid shaders, ARB2 is default nowadays and we override the interaction shaders with GLSL anyway if availiable. static progDef_t progs[MAX_GLPROGS] = { {GL_VERTEX_PROGRAM_ARB, VPROG_TEST, "test.vfp"}, {GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST, "test.vfp"}, {GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION, "interaction.vfp"}, {GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION, "interaction.vfp"}, {GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp"}, {GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp"}, {GL_VERTEX_PROGRAM_ARB, VPROG_AMBIENT, "ambientLight.vfp"}, {GL_FRAGMENT_PROGRAM_ARB, FPROG_AMBIENT, "ambientLight.vfp"}, {GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW, "shadow.vp"}, {GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT, "environment.vfp"}, {GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT, "environment.vfp"}, // additional programs can be dynamically specified in materials }; /* ================= R_LoadARBProgram ================= */ void R_LoadARBProgram( int progIndex ) { int ofs; int err; idStr fullPath = "glprogs/"; fullPath += progs[progIndex].name; char *fileBuffer; char *buffer; char *start = '\0', *end; common->Printf( "%s", fullPath.c_str() ); // load the program even if we don't support it, so // fs_copyfiles can generate cross-platform data dumps fileSystem->ReadFile( fullPath.c_str(), ( void ** ) &fileBuffer, NULL ); if( !fileBuffer ) { common->Printf( ": File not found\n" ); return; } // copy to stack memory and free buffer = static_cast( _alloca( strlen( fileBuffer ) + 1 ) ); strcpy( buffer, fileBuffer ); fileSystem->FreeFile( fileBuffer ); if( !glConfig.isInitialized ) { return; } // submit the program string at start to GL if( progs[progIndex].ident == 0 ) { // allocate a new identifier for this program progs[progIndex].ident = PROG_USER + progIndex; } // vertex and fragment programs can both be present in a single file, so // scan for the proper header to be the start point, and stamp a 0 in after the end if( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) { if( !glConfig.ARBVertexProgramAvailable ) { common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" ); return; } start = strstr( ( char * ) buffer, "!!ARBvp" ); } if( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) { if( !glConfig.ARBFragmentProgramAvailable ) { common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" ); return; } start = strstr( ( char * ) buffer, "!!ARBfp" ); } if( !start ) { common->Printf( ": !!ARB not found\n" ); return; } end = strstr( start, "END" ); if( !end ) { common->Printf( ": END not found\n" ); return; } end[3] = 0; glBindProgramARB( progs[progIndex].target, progs[progIndex].ident ); glGetError(); glProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB, strlen( start ), ( unsigned char * ) start ); err = glGetError(); glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, ( GLint * ) &ofs ); if( err == GL_INVALID_OPERATION ) { const GLubyte *str = glGetString( GL_PROGRAM_ERROR_STRING_ARB ); common->DWarning( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str ); if( ofs < 0 ) { common->DWarning( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" ); } else if( ofs >= ( int ) strlen( ( char * ) start ) ) { common->DWarning( "error at end of program\n" ); } else { common->DWarning( "error at %i:\n%s", ofs, start + ofs ); } return; } if( ofs != -1 ) { common->DWarning( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" ); return; } common->Printf( "\n" ); // need to strip the extension. fullPath.StripFileExtension(); // output separated fragment / vertex shaders. if ( r_printGLProgs.GetBool() ) { if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) { fileSystem->WriteFile( ( fullPath + ".fp" ).c_str(), start, strlen( start ) ); } else { fileSystem->WriteFile( ( fullPath + ".vp" ).c_str(), start, strlen( start ) ); } } } /* ================== R_FindARBProgram Returns a GL identifier that can be bound to the given target, parsing a text file if it hasn't already been loaded. ================== */ int R_FindARBProgram( GLenum target, const char *program ) { int i; idStr stripped = program; stripped.StripFileExtension(); // see if it is already loaded for( i = 0; progs[i].name[0]; i++ ) { if( progs[i].target != target ) { continue; } idStr compare = progs[i].name; compare.StripFileExtension(); if( !idStr::Icmp( stripped.c_str(), compare.c_str() ) ) { return progs[i].ident; } } if( i == MAX_GLPROGS ) { common->Error( "R_FindARBProgram: MAX_GLPROGS" ); } // add it to the list and load it progs[i].ident = ( program_t ) 0; // will be gen'd by R_LoadARBProgram progs[i].target = target; strncpy( progs[i].name, program, sizeof( progs[i].name ) - 1 ); R_LoadARBProgram( i ); common->Printf( "Finding program %s\n", program ); return progs[i].ident; } /* ================== GL_GetShaderInfoLog ================== */ static void GL_GetShaderInfoLog( GLuint s, GLchar *src, bool isprog ) { static GLchar infolog[4096]; GLsizei outlen = 0; infolog[0] = 0; if( isprog ) { glGetProgramInfoLog( s, 4095, &outlen, infolog ); } else { glGetShaderInfoLog( s, 4095, &outlen, infolog ); } common->Warning( "Shader Source:\n\n%s\n\n%s\n\n", src, infolog ); } /* ================== GL_CompileShader ================== */ static bool GL_CompileShader( GLuint sh, GLchar *src ) { if( sh && src ) { GLint result = GL_FALSE; glGetError(); glShaderSource( sh, 1, ( const GLchar ** )&src, NULL ); glCompileShader( sh ); glGetShaderiv( sh, GL_COMPILE_STATUS, &result ); if( result != GL_TRUE ) { GL_GetShaderInfoLog( sh, src, false ); return false; } else if( glGetError() != GL_NO_ERROR ) { GL_GetShaderInfoLog( sh, src, false ); } } return true; } //=================================================================================== struct glsltable_t { GLuint slot; GLchar *name; }; // doom actually emulates immediate function modes with quite a bit of the vertex attrib calls, like glVertex3f = attrPosition or glColor3/4f = attribColor etc. // this is also the reason our first attempts at replacing them with vertex array pointers failed, // because those index positions are not declared in the shader at all. // the uncommented ones below are the ones missing from the shaders, // i only left them in in case someone wanted to make an effort in that regard. glsltable_t interactionAttribs[] = { /*{0, "attrPosition"}, // does not exist in shader {2, "attrNormal"}, // ditto and we have two normal indexes (one is used to get texture coordinates for skyportals) {3, "attrColor"},*/ // sigh... { 8, "attrTexCoords" }, { 9, "attrTangents0" }, { 10, "attrTangents1" }, { 11, "attrNormal" } }; /* ================== GL_CreateGLSLProgram Checks and creates shader programs for GLSL Modified to throw invalid program if something fails. ================== */ static GLuint GL_CreateGLSLProgram( GLchar *vssrc, GLchar *fssrc, glsltable_t *attribs, GLuint numattribs ) { GLuint progid; GLuint vs = vssrc ? glCreateShader( GL_VERTEX_SHADER ) : INVALID_PROGRAM; GLuint fs = fssrc ? glCreateShader( GL_FRAGMENT_SHADER ) : INVALID_PROGRAM; glGetError(); // vertex shader failed to compile if( vs && vssrc && !GL_CompileShader( vs, vssrc ) ) { return INVALID_PROGRAM; } // fragment shader failed to compile if( fs && fssrc && !GL_CompileShader( fs, fssrc ) ) { return INVALID_PROGRAM; } progid = glCreateProgram(); if( vs && vssrc ) { glAttachShader( progid, vs ); } if( fs && fssrc ) { glAttachShader( progid, fs ); } // bind attrib index numbers // we could actually bind the emulated ones here as well and then vertex attribs should work. if( attribs && numattribs ) { for( GLuint i = 0; i < numattribs; i++ ) { glBindAttribLocation( progid, attribs[i].slot, attribs[i].name ); } } GLint result = GL_FALSE; glLinkProgram( progid ); glGetProgramiv( progid, GL_LINK_STATUS, &result ); glDeleteShader( vs ); glDeleteShader( fs ); if( result != GL_TRUE ) { GL_GetShaderInfoLog( progid, "", true ); return INVALID_PROGRAM; } return progid; } //=================================================================================== struct sampleruniforms_t { GLchar *name; GLint binding; }; sampleruniforms_t rb_interactionsamplers[] = { { "bumpImage", 1 }, { "lightFalloffImage", 2 }, { "lightProjectImage", 3 }, { "diffuseImage", 4 }, { "specularImage", 5 } }; /* ================== GL_SetupSamplerUniforms ================== */ static void GL_SetupSamplerUniforms( GLuint progid, sampleruniforms_t *uniForms, GLuint numUniforms ) { // setup uniform locations - this is needed even on nvidia glUseProgram( progid ); for( GLuint i = 0; i < numUniforms; i++ ) { glUniform1i( glGetUniformLocation( progid, uniForms[i].name ), uniForms[i].binding ); } } /* ================== GL_GetGLSLFromFile ================== */ static GLchar *GL_GetGLSLFromFile( const GLchar *name ) { idStr fullPath = "glprogs130/"; fullPath += name; GLchar *fileBuffer; GLchar *buffer; if( !glConfig.isInitialized ) { return NULL; } common->Printf( "%s", fullPath.c_str() ); fileSystem->ReadFile( fullPath.c_str(), reinterpret_cast( &fileBuffer ), NULL ); if( !fileBuffer ) { common->Printf( ": File not found, using internal shaders\n" ); return NULL; } // copy to stack memory buffer = reinterpret_cast( Mem_Alloc( strlen( fileBuffer ) + 1 ) ); strcpy( buffer, fileBuffer ); fileSystem->FreeFile( fileBuffer ); common->Printf( "\n" ); return buffer; } /* ================== R_ReloadARBPrograms_f ================== */ void R_ReloadARBPrograms_f( const idCmdArgs &args ) { common->Printf( "----- R_ReloadARBPrograms -----\n" ); for( int i = 0; progs[i].name[0]; i++ ) { R_LoadARBProgram( i ); } // load GLSL interaction programs if enabled if( glConfig.ARBShadingLanguageAvailable ) { common->Printf( "----- Using GLSL interactions (forced) -----\n" ); // according to khronos this might not actually delete the shader program. glDeleteProgram( rb_glsl_interaction_program ); // try to load from file, use internal shader if not available. GLchar *vs = GL_GetGLSLFromFile( "interaction_vs.glsl" ); GLchar *fs = GL_GetGLSLFromFile( "interaction_fs.glsl" ); // replace ARB interaction shaders with GLSL counterparts, it is possible to use external GLSL shaders as well. rb_glsl_interaction_program = GL_CreateGLSLProgram( ( vs != NULL ) ? vs : interaction_vs, ( fs != NULL ) ? fs : interaction_fs, interactionAttribs, sizeof( interactionAttribs ) / sizeof( interactionAttribs[0] ) ); // free externally loaded vertex shader. if( vs != NULL ) { Mem_Free( vs ); } // free externally loaded fragment shader. if( fs != NULL ) { Mem_Free( fs ); } // if the shader did not run into problems load it up. if( rb_glsl_interaction_program != INVALID_PROGRAM ) { // made sure shaders are valid coming in here GL_SetupSamplerUniforms( rb_glsl_interaction_program, rb_interactionsamplers, sizeof( rb_interactionsamplers ) / sizeof( rb_interactionsamplers[0] ) ); // set shader uniforms u_light_origin = glGetUniformLocation( rb_glsl_interaction_program, "u_light_origin" ); u_view_origin = glGetUniformLocation( rb_glsl_interaction_program, "u_view_origin" ); u_color_modulate = glGetUniformLocation( rb_glsl_interaction_program, "u_color_modulate" ); u_color_add = glGetUniformLocation( rb_glsl_interaction_program, "u_color_add" ); u_constant_diffuse = glGetUniformLocation( rb_glsl_interaction_program, "u_constant_diffuse" ); u_constant_specular = glGetUniformLocation( rb_glsl_interaction_program, "u_constant_specular" ); u_diffMatrix = glGetUniformLocation( rb_glsl_interaction_program, "u_diffMatrix" ); u_bumpMatrix = glGetUniformLocation( rb_glsl_interaction_program, "u_bumpMatrix" ); u_specMatrix = glGetUniformLocation( rb_glsl_interaction_program, "u_specMatrix" ); u_projMatrix = glGetUniformLocation( rb_glsl_interaction_program, "u_projMatrix" ); u_fallMatrix = glGetUniformLocation( rb_glsl_interaction_program, "u_fallMatrix" ); } glUseProgram( INVALID_PROGRAM ); } common->Printf( "-------------------------------\n" ); } /* ================== R_ARB2_Init ================== */ void R_ARB2_Init( void ) { glConfig.allowARB2Path = false; common->Printf( "---------- R_ARB2_Init ----------\n" ); if( !glConfig.ARBVertexProgramAvailable || !glConfig.ARBFragmentProgramAvailable ) { common->DWarning( "Not available.\n" ); return; } common->Printf( "Available.\n" ); common->Printf( "---------------------------------\n" ); glConfig.allowARB2Path = true; } ```

This will override the ARB2 assembly shaders with GLSL if your card supports it. The benefit is that we can still use things like sikkmod (tested), and the internal GLSL interaction shader looks better than sikkmods. One downside though is that we cannot use sikkpins parallax shader unless we create a cvar for turning of GLSL completely, since sikkpins parralax shader is an interaction shader.

This code was originally by michael hiney, but it had a few bugs that i been working over the years to iron out, since im not very well versed in shaders it took longer than i expected but it works rather well now.

Next thing would be GLSL for the stencil shadows, though if we want to still be able to use things like sikkmods soft shadows, it will be nessesary with a cvar to turn it of.

revelator commented 4 years ago

Ported my work on the hybrid GLSL / ARB2 backend and uploaded a 32 bit windows build here.

(https://sourceforge.net/projects/cbadvanced/files/Game%20Projects/dhewm3-with-glsl-interactions.7z/download)

not much improvement speedwise, maybe 1 fps, it might actually gain more with things like sikkmod. Also ported a few things from darkmod like SSE enhanced matrix operations, still need to get the SMP code ported and then there is also the SSE enhanced Culling code from darkmod.

R_testGLSLInteractions is on by default, but if you want to toy with seeing the differences between the two render backends just set it to 0 ( you might not actually see much since its pretty close to the original ARB2 based renderer in regards to the overall look, the GLSL backend is a bit crisper though ).

DanielGibson commented 4 years ago

However, there is no Sikkmod for dhewm3 because the C++ code is not released under GPL?

ghost commented 4 years ago

You're the only one who cares.

DanielGibson commented 4 years ago

Yes, but I'm running this project.

revelator commented 4 years ago

I have sikkmods game code, i doubt that it was intentional that it was not released under GPL since i been doing collaborate work with sikkpin some years back and he newer expressed any resentment against anyone using the game code. However im not sure where he resides these days since i been on hiatus due to bad health for several years, so contacting him might be hard.

revelator commented 4 years ago

Code is still worthwhile if not for other reasons than that it gives us more options. Newer coders might be more into GLSL than assembler these days anyway :)

coreyoconnor commented 4 years ago

I definitely care. Don't let the negative folks discourage you :)

And yea, I'm still thinking an ARB to GLSL translator would be a valuable product. Too bad I'm full with other stuff :(

ghost commented 4 years ago

I think you're confused, @coreyoconnor .

I'm all for implementing Sikkpin's code. If he didn't want this, he wouldn't have published it.

revelator commented 4 years ago

Well to be sure theres no problem, and i doubt that... i contacted sikkpin via his old information on insideqc. Lets see if he still reads the PM's there.

So for the heck of it i tried building sikkmods game dll with the sdk, and it runs quite good here with the hybrid code. But tbh my gfx card while last last gen still has the muscle to run the newest games with playable fps ( AMD R9 390 ), so it might not be the best pointer, biggest fps hog seems to be the parallax interaction shader ( need to run the game with GLSL off for that one ) and soft shadows. These two rip about 20 -> 30 fps alone. There are also better options for softshadows today since we can now access the depthbuffer in Doom3 ( this feature was added to darkmod some years back by me and SteveL ).

SSAO runs fine on this card maybe 1 -> 2 fps less.

Ported AVX and AVX2 from darkmod to my test engine ( not dhewm based ) and it gives a neat boost ( around 8 -> 10 fps ).

Also started porting the SMP code ( so far only the async thread timer update code has made it in ) but atleast that takes care of the microstutter sometimes noticed.

The timer now uses microseconds instead of milliseconds so resolution had to be changed from 16 ms to 3 ms or it would cause double frames.

DanielGibson commented 4 years ago

Don't get me wrong, I'm all for GLSL support, I'm just skeptical about Sikkmod - but we can have one thing without the other!

Would be cool if you could reach Sikkpin - I tried contacting him via E-Mail twice (I think) but never got any answer :-/ The last "public record" of him is that he logged into moiddb in 2012: https://www.moddb.com/members/sikkpin it's like he vanished afterwards

If he didn't want this, he wouldn't have published it.

It's not that easy. Under SDK license the code could only be used in noncommercial Doom3 Mods. Under GPL it can be used for anything, as long as the product's source code is available - including commercial games (and there are commercial games using GPL'ed id Software engines, e.g. SteelStorm or the Blendo Games). We don't know how Sikkpin feels about his code potentially being used for commercial projects (without him getting any money for it), so I don't think it's OK to just put it under GPL. Unless he agrees or has agreed to it in the past - I couldn't find anything on that matter, but Doom3world is down and much of it is missing on archive.org, so no idea..

revelator commented 4 years ago

Well he spent some time on insideqc after doom3world went down, but that is also some years back. I pretty much got his permission to use his shaders as i saw fit, though we newer discussed any commercial projects.

So im as curious as you if he answers.

But i guess the problem lies in the game code ?, allthough by default it should follow id's licensing.

DanielGibson commented 4 years ago

Yes, the problem is the game code. And id's default licensing was the SDK license - this was way before Doom3's source code was released under GPL. So to use old mod's source code with a GPL source port like dhewm3, the code must be re-licensed under GPL (specifically the flavor Doom3 uses, which is GPLv3 with some additional clauses from Zenimax). Re-licensing means that everyone who contributed C++ code to the mod must agree that it's released under GPL - I was able to get that OK from several mod teams for https://github.com/dhewm/dhewm3-sdk, but there were also people who didn't want their code to (potentially) be used in commercial games...

motorsep commented 4 years ago

If there is GLSL backend, I am sure it would be easier to find someone to write new GLSL shaders than look for Sikkpin for permission to use his mod in Dhewm3

Arl90 commented 4 years ago

I remember Sikkmod required a lot of asset adaptation to properly work with shadows, like adding a duplicated mesh in each md5 file with a shadow material for self shadowing and such, and a lot of .mtr overrides.

Not an ideal approach for a graphical enhancement, but that's just me.

revelator commented 4 years ago

Well no reply from him yet but lets see.

Atm the backend only handles the interactions for bump / specular / diffuse so it should be relatively easy to write new shaders for it, though it would be limited what you could do ( parallax occlusion mapping in GLSL is one example that should be possible ).

At some point im going to try and port more stuff from darkmod like framebuffers / depthbuffer access / and expand the GLSL capability to also include material shaders and shadows, but that might take a while since im pretty much retired as a coder, and only dabble in it from time to time to keep my skills.

Sikkmod was just an example to show that the backend could handle mixing in with older mods without to much trouble, and granted it uses some nasty workarounds, but at the time we did not have access to the engine code so i think sikkpin made as good a job as he could with the limitations at the time.

motorsep commented 4 years ago

Well, if shaders will be written from scratch, why hold on to ARB shaders at all?

revelator commented 4 years ago

Just a compatibility question really, fhDoom while fully GLSL driven still does not play the expansion because of missing shaders and since im no shader guru that part is more upto the userbase that has experience with coding in glslang.

Id rather not break the code for the dhewm maintainer so im going for the baby steps approach atm. When im satisfied things work without problems ill upload a patch he can yank in to the engine if he feels the need is there :)

motorsep commented 4 years ago

there is a reason I recommend using RBDoom 3 BFG's renderer - it has all GLSL shaders.

revelator commented 4 years ago

Tbh my intentions with this was mostly to get a working hybrid backend going which daniel could then build on, i newer had any intention of doing a full GLSL backend since it seems daniel cares about old mod compatibility which this one provides.

Im retired, but over the time i made a few neat things that might benefit others, but Im not going to turn it into a full time job again no matter who cries. :P

Im simply getting to old for the kind of workload such an undertaking would require, and as you seen i had my fair share of bedcare in the hospital wards ( broken back "10 years walking around or trying to since i could only go about 100 meters, before the doctors noticed" -> kidney stones "twice now and more to come" -> gall stones "luckily only once but damn" -> nerve damage "irreperable damage because of the broken back" you name it... ).

Ill still provide tidbits that might come in handy from time to time though.

ghost commented 4 years ago

since it seems daniel cares about old mod compatibility

... which is a complete dead end, especially because of insisting doing things by the book. I seriously doubt the amount of old mods supported by dhewm3 will even grow beyond what it supports at the moment, because everyone moved on well over a decade ago.

revelator commented 4 years ago

Noone discurages anyone from updating anything :) if the demand is there it will come.

That said there exists a number of engines that have much more modern capabilities, fhDoom for instance or RBDoom both support GLSL fully and have shadowmaps and whatnot.

If one prefers the older tech 4 engine fhDoom is the way to go, otherwise RBDoom or motorseps steelstorm engine are pretty nice.

I cannot speak for cross compatibility though, but from what i heard both engines can be built on linux as well.

fhDooms main problem atm is the lack of shaders for the expension ( it pretty much only plays Doom3 at the moment but looks good ), RBDoom has a nasty bug with HDR and SSAO which causes black splotches on AMD cards if both are on, but it can play both Doom3 plus the expansion and has a good deal of shaders for experimenting on.

fhDoom has parallax mapping but no SSAO, and parallax mapping is of by default because some of Doom3's heightmaps are bad causing glitches like we seen in sikkmod with sliding textures on some environments.

Darkmod also has enhanced capabilities like full GLSL capability and to top that off it can also still use some of the older ARB2 shaders, but you cannot play Doom3 with it anymore since it is now a total conversion of the old thief game.

Some features from it can be ported to other Doom3 engines though and im toying with that atm.

ghost commented 4 years ago

if the demand is there it will come

Demand won't come until a mod that grabs people's attention does.

revelator commented 4 years ago

Well darkmod certainly did just that :) it won an award. Sadly it is not usable as is for Doom3 because of the many changes to the engine. The source is open though, so anyone could create a mod with it. At times i wished i had any skill whatsoever in mapping, i allways wanted to create a game from scratch.

Unfortunatly i cant draw anything without breaking both pen and paper hehe. I do have an idea for a game, but it would require someone with skills in mapping / modelling as the only other thing i could contribute besides code would be sound ( old guitar and bass player ).

Just out of curiosity, have you tried the mod redux ?. It updates Doom3 graphics somewhat using nothing but optimized shaders / corrected materials / HD textures, and a special handcrafted version of the old venom menu. It looks rather good but loading time is slow as molasses.

Its actually a pity that it is a mod because it would have been a nice update to Doom3 itself.

Arl90 commented 4 years ago

Revelator, is really cool what you are doing of porting some TDM features, it has a lot of goodies, maybe this could open the doors for some devs to enhance the engine a bit, if not in dhewm 3 maybe in some other fork.

fhDoom is very nice, but sadly the developer has gone silent and work on it stalled some time ago.