From 6449d22d7ffc3a12e61b82c4891ab8a5f7311599 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Sun, 1 Mar 2026 12:18:30 +0000 Subject: [PATCH 1/4] opengl debug committing to test on windows with proper debug output --- Engine/source/gfx/gl/gfxGLDevice.cpp | 122 ++++++++++++++----- Engine/source/gfx/gl/gfxGLTextureManager.cpp | 99 +++++++++++---- Engine/source/gfx/gl/gfxGLTextureObject.cpp | 93 ++++++++++---- Engine/source/gfx/gl/gfxGLUtils.h | 26 ++++ Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp | 10 +- Engine/source/platformSDL/sdlPlatformGL.cpp | 4 +- 6 files changed, 270 insertions(+), 84 deletions(-) diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 8019f21bf..8ec644b8a 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -91,19 +91,74 @@ void loadGLExtensions(void *context) GL::gglPerformExtensionBinds(context); } -void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, - const GLchar *message, const void *userParam) +void APIENTRY glDebugCallback( + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) { - // JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes. - // This only happens on Intel cards. This should be looked into sometime in the near future. - if (dStrStartsWith(message, "API_ID_REDUNDANT_FBO")) + // Ignore non-significant notifications (optional) + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return; + + const char* srcStr = "UNKNOWN"; + const char* typeStr = "UNKNOWN"; + const char* sevStr = "UNKNOWN"; + + switch (source) + { + case GL_DEBUG_SOURCE_API: srcStr = "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: srcStr = "WINDOW"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: srcStr = "SHADER"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: srcStr = "THIRD_PARTY"; break; + case GL_DEBUG_SOURCE_APPLICATION: srcStr = "APP"; break; + case GL_DEBUG_SOURCE_OTHER: srcStr = "OTHER"; break; + } + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: typeStr = "ERROR"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeStr = "DEPRECATED"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeStr = "UNDEFINED"; break; + case GL_DEBUG_TYPE_PORTABILITY: typeStr = "PORTABILITY"; break; + case GL_DEBUG_TYPE_PERFORMANCE: typeStr = "PERFORMANCE"; break; + case GL_DEBUG_TYPE_MARKER: typeStr = "MARKER"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: typeStr = "PUSH"; break; + case GL_DEBUG_TYPE_POP_GROUP: typeStr = "POP"; break; + case GL_DEBUG_TYPE_OTHER: typeStr = "OTHER"; break; + } + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: sevStr = "HIGH"; break; + case GL_DEBUG_SEVERITY_MEDIUM: sevStr = "MEDIUM"; break; + case GL_DEBUG_SEVERITY_LOW: sevStr = "LOW"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: sevStr = "NOTIFY"; break; + } + + // Filter known noisy IDs here if needed + // Example: + // if (id == 131185) return; + if (severity == GL_DEBUG_SEVERITY_HIGH) - Con::errorf("OPENGL: %s", message); + { + Con::errorf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + AssertFatal(false, "OpenGL HIGH severity error."); + } else if (severity == GL_DEBUG_SEVERITY_MEDIUM) - Con::warnf("OPENGL: %s", message); - else if (severity == GL_DEBUG_SEVERITY_LOW) - Con::printf("OPENGL: %s", message); + { + Con::warnf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + } + else + { + Con::printf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + } } void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, @@ -157,27 +212,34 @@ void GFXGLDevice::initGLState() #endif #if TORQUE_DEBUG - if( gglHasExtension(ARB_debug_output) ) - { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallbackARB(glDebugCallback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - GLuint unusedIds = 0; - glDebugMessageControlARB(GL_DONT_CARE, - GL_DONT_CARE, - GL_DONT_CARE, - 0, - &unusedIds, - GL_TRUE); - } - else if(gglHasExtension(AMD_debug_output)) - { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallbackAMD(glAmdDebugCallback, NULL); - //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - GLuint unusedIds = 0; - glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE); - } + +bool debugInitialized = false; +int flags; +glGetIntegerv(GL_CONTEXT_FLAGS, &flags); +if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) +{ + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + + glDebugMessageCallback(glDebugCallback, nullptr); + + glDebugMessageControl( + GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + nullptr, + GL_TRUE); + + Con::printf("OpenGL debug output enabled."); + debugInitialized = true; +} + +if (!debugInitialized) +{ + Con::warnf("OpenGL debug output NOT available."); +} + #endif PlatformGL::setVSync(smEnableVSync); diff --git a/Engine/source/gfx/gl/gfxGLTextureManager.cpp b/Engine/source/gfx/gl/gfxGLTextureManager.cpp index ca0a958f3..c6c73fbee 100644 --- a/Engine/source/gfx/gl/gfxGLTextureManager.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureManager.cpp @@ -175,7 +175,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, //calculate num mipmaps if(retTex->mMipLevels == 0) retTex->mMipLevels = getMaxMipmaps(width, height, 1); - + glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 ); bool hasTexStorage = false; @@ -364,34 +364,83 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, // loadTexture - GBitmap //----------------------------------------------------------------------------- -static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerPixel,const GFXGLTextureObject* texture, const GFXFormat fmt, const U8* data,const S32 mip=0, const U32 face = 0, Swizzle *pSwizzle = NULL) +static void _textureUpload( + const S32 width, + const S32 height, + const S32 bytesPerPixel, + const GFXGLTextureObject* texture, + const GFXFormat fmt, + const U8* data, + const S32 mip = 0, + const U32 face = 0, + Swizzle* pSwizzle = NULL) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->getBuffer()); - U32 bufSize = width * height * bytesPerPixel; - glBufferData(GL_PIXEL_UNPACK_BUFFER, bufSize, NULL, GL_STREAM_DRAW); + const GLenum target = texture->getBinding(); - if(pSwizzle) - { - PROFILE_SCOPE(Swizzle32_Upload); - U8* pboMemory = (U8*)dMalloc(bufSize); - pSwizzle->ToBuffer(pboMemory, data, bufSize); - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pboMemory); - dFree(pboMemory); - } - else - { - PROFILE_SCOPE(SwizzleNull_Upload); - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, data); - } + // Save pixel store state + GLint prevUnpackAlign; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign); - if(texture->getBinding() == GL_TEXTURE_CUBE_MAP) - glTexSubImage2D(GFXGLFaceType[face], mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); - else if (texture->getBinding() == GL_TEXTURE_2D) - glTexSubImage2D(texture->getBinding(), mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); - else - glTexSubImage1D(texture->getBinding(), mip, 0, (width > 1 ? width : height), GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + const U32 bufSize = width * height * bytesPerPixel; + + const U8* uploadPtr = data; + U8* tempBuffer = nullptr; + + if (pSwizzle) + { + tempBuffer = (U8*)dMalloc(bufSize); + pSwizzle->ToBuffer(tempBuffer, data, bufSize); + uploadPtr = tempBuffer; + } + + if (target == GL_TEXTURE_CUBE_MAP) + { + glTexSubImage2D( + GFXGLFaceType[face], + mip, + 0, 0, + width, height, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + else if (target == GL_TEXTURE_2D) + { + glTexSubImage2D( + GL_TEXTURE_2D, + mip, + 0, 0, + width, height, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + else if (target == GL_TEXTURE_1D) + { + glTexSubImage1D( + GL_TEXTURE_1D, + mip, + 0, + width, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + + if (tempBuffer) + dFree(tempBuffer); + + // Restore state + glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign); + +#ifdef TORQUE_DEBUG + glCheckErrors(); +#endif } bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL) diff --git a/Engine/source/gfx/gl/gfxGLTextureObject.cpp b/Engine/source/gfx/gl/gfxGLTextureObject.cpp index 651059d34..81ca6fa9d 100644 --- a/Engine/source/gfx/gl/gfxGLTextureObject.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureObject.cpp @@ -102,36 +102,79 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel /*= 0*/, RectI* inRect /*= void GFXGLTextureObject::unlock(U32 mipLevel /*= 0*/, U32 faceIndex /*= 0*/) { - if(!mLockedRect.bits) - return; + if (!mLockedRect.bits) + return; - // I know this is in unlock, but in GL we actually do our submission in unlock. - PROFILE_SCOPE(GFXGLTextureObject_lockRT); + PROFILE_SCOPE(GFXGLTextureObject_unlock); - PRESERVE_TEXTURE(mBinding); - glBindTexture(mBinding, mHandle); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mBuffer); - glBufferData(GL_PIXEL_UNPACK_BUFFER, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW); - S32 z = getDepth(); - if (mBinding == GL_TEXTURE_3D) - glTexSubImage3D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, z, - mLockedRectRect.extent.x, mLockedRectRect.extent.y, z, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); - else if(mBinding == GL_TEXTURE_2D) - glTexSubImage2D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, - mLockedRectRect.extent.x, mLockedRectRect.extent.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); - else if(mBinding == GL_TEXTURE_1D) - glTexSubImage1D(mBinding, mipLevel, (mLockedRectRect.point.x > 1 ? mLockedRectRect.point.x : mLockedRectRect.point.y), - (mLockedRectRect.extent.x > 1 ? mLockedRectRect.extent.x : mLockedRectRect.extent.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); + PRESERVE_TEXTURE(mBinding); + glBindTexture(mBinding, mHandle); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + // --- Save pixel store state --- + GLint prevUnpackAlign; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign); - mLockedRect.bits = NULL; -#if TORQUE_DEBUG - AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), ""); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + const U32 width = mLockedRectRect.extent.x; + const U32 height = mLockedRectRect.extent.y; + const U32 depth = getDepth(); + + if (mBinding == GL_TEXTURE_3D) + { + glTexSubImage3D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + mLockedRectRect.point.y, + 0, + width, + height, + depth, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + else if (mBinding == GL_TEXTURE_2D) + { + glTexSubImage2D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + mLockedRectRect.point.y, + width, + height, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + else if (mBinding == GL_TEXTURE_1D) + { + glTexSubImage1D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + width, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + + // --- Restore state --- + glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign); + + mLockedRect.bits = NULL; + + FrameAllocator::setWaterMark(mFrameAllocatorMark); + mFrameAllocatorMark = 0; + mFrameAllocatorPtr = NULL; + +#ifdef TORQUE_DEBUG + glCheckErrors(); #endif - FrameAllocator::setWaterMark(mFrameAllocatorMark); - mFrameAllocatorMark = 0; - mFrameAllocatorPtr = NULL; } void GFXGLTextureObject::release() diff --git a/Engine/source/gfx/gl/gfxGLUtils.h b/Engine/source/gfx/gl/gfxGLUtils.h index 2218836b0..928cf98e3 100644 --- a/Engine/source/gfx/gl/gfxGLUtils.h +++ b/Engine/source/gfx/gl/gfxGLUtils.h @@ -28,6 +28,32 @@ #include "gfx/gl/gfxGLStateCache.h" #include "gfx/bitmap/imageUtils.h" +inline const char* glGetErrorString(GLenum error) +{ + switch (error) + { + case GL_NO_ERROR: return "No Error"; + case GL_INVALID_ENUM: return "Invalid Enum"; + case GL_INVALID_VALUE: return "Invalid Value"; + case GL_INVALID_OPERATION: return "Invalid Operation"; + case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation"; + case GL_OUT_OF_MEMORY: return "Out of Memory"; + case GL_STACK_UNDERFLOW: return "Stack Underflow"; + case GL_STACK_OVERFLOW: return "Stack Overflow"; + case GL_CONTEXT_LOST: return "Context Lost"; + default: return "Unknown Error"; + } +} + +inline void _glCheckErrors(const char *filename, int line) +{ + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) + Con::printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err)); +} + +#define glCheckErrors() _glCheckErrors(__FILE__, __LINE__) + inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth) { return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height))) + 1; diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 1bb34d4f2..a81c0334c 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -103,9 +103,17 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) } SDL_ClearError(); + U32 debugFlag = 0; +#ifdef TORQUE_DEBUG + debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; +#endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1); - + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); +#ifdef TORQUE_GL_SOFTWARE + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0); +#endif SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow ); if( !tempContext ) { diff --git a/Engine/source/platformSDL/sdlPlatformGL.cpp b/Engine/source/platformSDL/sdlPlatformGL.cpp index fd55727b8..22e719f58 100644 --- a/Engine/source/platformSDL/sdlPlatformGL.cpp +++ b/Engine/source/platformSDL/sdlPlatformGL.cpp @@ -19,12 +19,10 @@ namespace PlatformGL #ifdef TORQUE_DEBUG debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; #endif - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, majorOGL); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); #ifdef TORQUE_GL_SOFTWARE SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0); #endif From cf294ad12181309f30e63f7e17b4745e3babb4cb Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 2 Mar 2026 08:52:47 -0600 Subject: [PATCH 2/4] selfshadowing corrections best to stick to the order of the XY tags use PI, not 1/PI to avoid "normal flipping" --- .../game/core/rendering/shaders/gl/lighting.glsl | 10 +++++----- .../game/core/rendering/shaders/lighting.hlsl | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl index 0ebcd3794..a1df93c70 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl @@ -178,9 +178,9 @@ SurfaceToLight createSurfaceToLight(in Surface surface, in vec3 L) surfaceToLight.Lu = L; surfaceToLight.L = normalize(L); surfaceToLight.H = normalize(surface.V + surfaceToLight.L); - surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N)); - surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V)); - surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N)); + surfaceToLight.NdotL = saturate(dot(surface.N,surfaceToLight.L)); + surfaceToLight.HdotV = saturate(dot(surfaceToLight.H,surface.V)); + surfaceToLight.NdotH = saturate(dot(surface.N,surfaceToLight.H)); return surfaceToLight; } @@ -243,12 +243,12 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; vec3 specularBRDF = numerator / denominator; - vec3 diffuseBRDF = surface.baseColor.rgb * M_1OVER_PI_F * surface.ao; + vec3 diffuseBRDF = surface.baseColor.rgb * surface.ao * M_PI_F; // Final output combining all terms vec3 kS = F; // Specular reflectance vec3 kD = (1.0 - kS) * (1.0 - surface.metalness); // Diffuse reflectance - vec3 returnBRDF = kD * (diffuseBRDF) + specularBRDF; + vec3 returnBRDF = kD * diffuseBRDF + specularBRDF; if(isCapturing == 1) return lerp(returnBRDF ,surface.albedo.rgb,surface.metalness); diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index a2e8d2f4e..015c925bf 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -177,9 +177,9 @@ inline SurfaceToLight createSurfaceToLight(in Surface surface, in float3 L) surfaceToLight.Lu = L; surfaceToLight.L = normalize(L); surfaceToLight.H = normalize(surface.V + surfaceToLight.L); - surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N)); + surfaceToLight.NdotL = saturate(dot(surface.N, surfaceToLight.L)); surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V)); - surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N)); + surfaceToLight.NdotH = saturate(dot(surface.N, surfaceToLight.H)); return surfaceToLight; } @@ -243,12 +243,12 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; float3 specularBRDF = numerator / denominator; - float3 diffuseBRDF = surface.baseColor.rgb * M_1OVER_PI_F * surface.ao; + float3 diffuseBRDF = surface.baseColor.rgb * surface.ao* M_PI_F; // Final output combining all terms float3 kS = F; // Specular reflectance float3 kD = (1.0 - kS) * (1.0 - surface.metalness); // Diffuse reflectance - float3 returnBRDF = kD * (diffuseBRDF) + specularBRDF; + float3 returnBRDF = kD*diffuseBRDF + specularBRDF; if(isCapturing == 1) return lerp(returnBRDF ,surface.albedo.rgb,surface.metalness); @@ -277,8 +277,8 @@ float3 getPunctualLight(Surface surface, SurfaceToLight surfaceToLight, float3 l if(isCapturing != 1) lightfloor = 0.0; - float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); - + float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); + // Calculate both specular and diffuse lighting in one BRDF evaluation float3 directLighting = evaluateStandardBRDF(surface, surfaceToLight); @@ -297,7 +297,7 @@ float3 getSpotlight(Surface surface, SurfaceToLight surfaceToLight, float3 light float attenuation = 1.0f; attenuation *= getDistanceAtt(surfaceToLight.Lu, radius); attenuation *= getSpotAngleAtt(-surfaceToLight.L, lightDir, lightSpotParams.xy); - + // Calculate both specular and diffuse lighting in one BRDF evaluation float3 directLighting = evaluateStandardBRDF(surface, surfaceToLight); From 80f62573fea7fd64daf2b8eb5693d44582165107 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 2 Mar 2026 11:38:20 -0600 Subject: [PATCH 3/4] context safties and from Marauder, hardened filename entry for con::evaluate/compileexec. if the string forwarded along is not a real filename, consider it an eval block --- Engine/source/T3D/SubScene.cpp | 4 ++-- Engine/source/T3D/missionMarker.cpp | 4 ++-- Engine/source/T3D/trigger.cpp | 6 +++--- Engine/source/console/torquescript/codeBlock.cpp | 2 +- Engine/source/console/torquescript/runtime.cpp | 4 +++- .../source/gui/controls/guiGameListMenuCtrl.cpp | 2 +- Engine/source/gui/controls/guiListBoxCtrl.cpp | 2 +- Engine/source/gui/core/guiControl.cpp | 15 ++++++++------- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Engine/source/T3D/SubScene.cpp b/Engine/source/T3D/SubScene.cpp index 4dca81595..798d42ace 100644 --- a/Engine/source/T3D/SubScene.cpp +++ b/Engine/source/T3D/SubScene.cpp @@ -229,12 +229,12 @@ bool SubScene::evaluateCondition() if (objectName != NULL) objectName = getIdString(); - StringTableEntry groupName = getGroup()->getName(); + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; if (groupName != NULL) groupName = getGroup()->getIdString(); String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); - Con::evaluate(command.c_str(), false, context); + Con::evaluate(command.c_str(), false, context.c_str()); return Con::getBoolVariable(resVar.c_str()); } return true; diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index 9acf4c61c..a3e380951 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -372,12 +372,12 @@ bool SpawnSphere::testCondition() if (objectName != NULL) objectName = getIdString(); - StringTableEntry groupName = getGroup()->getName(); + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; if (groupName != NULL) groupName = getGroup()->getIdString(); String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); - Con::evaluate(command.c_str(), false, context); + Con::evaluate(command.c_str(), false, context.c_str()); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index 33075e70d..2558c45d5 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -711,12 +711,12 @@ bool Trigger::testCondition() if (objectName != NULL) objectName = getIdString(); - StringTableEntry groupName = getGroup()->getName(); + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; if (groupName != NULL) groupName = getGroup()->getIdString(); String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); - Con::evaluate(command.c_str(), false, context); + Con::evaluate(command.c_str(), false, context.c_str()); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; @@ -817,7 +817,7 @@ void Trigger::processTick(const Move* move) if (objectName != NULL) objectName = getIdString(); - StringTableEntry groupName = getGroup()->getName(); + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; if (groupName != NULL) groupName = getGroup()->getIdString(); diff --git a/Engine/source/console/torquescript/codeBlock.cpp b/Engine/source/console/torquescript/codeBlock.cpp index d3bf6b3f5..2696ca054 100644 --- a/Engine/source/console/torquescript/codeBlock.cpp +++ b/Engine/source/console/torquescript/codeBlock.cpp @@ -611,7 +611,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in Script::gStatementList = NULL; // we are an eval compile if we don't have a file name associated (no exec) - gIsEvalCompile = fileName == NULL; + gIsEvalCompile = fileName == NULL || setFrame == 0; gFuncVars = gIsEvalCompile ? &gEvalFuncVars : &gGlobalScopeFuncVars; // Set up the parser. diff --git a/Engine/source/console/torquescript/runtime.cpp b/Engine/source/console/torquescript/runtime.cpp index 45c3249ee..1f0db44d3 100644 --- a/Engine/source/console/torquescript/runtime.cpp +++ b/Engine/source/console/torquescript/runtime.cpp @@ -38,8 +38,10 @@ namespace TorqueScript if (fileName) fileName = StringTable->insert(fileName); + bool fileExec = Torque::FS::IsFile(fileName); + CodeBlock* newCodeBlock = new CodeBlock(); - return (newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0)); + return (newCodeBlock->compileExec(fileName, string, false, fileExec ? -1 : 0)); } Con::EvalResult TorqueScriptRuntime::evaluate(const char* script, S32 frame, bool echo, const char* fileName) diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index 2509c8cbd..6ceb1cbcd 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -976,7 +976,7 @@ void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command) setThisControl(); StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); - Con::evaluate(command, false, context); + Con::evaluate(command, false, context.c_str()); } } diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index 5a5a81e6a..58441dd46 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/Engine/source/gui/controls/guiListBoxCtrl.cpp @@ -1541,7 +1541,7 @@ StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj ) StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); - outName = StringTable->insert( Con::evaluate( mMakeNameCallback, false, context).value, true ); + outName = StringTable->insert( Con::evaluate( mMakeNameCallback, false, context.c_str()).value, true ); } else if ( inObj->getName() ) outName = StringTable->insert( inObj->getName() ); diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index b7b272612..bf9eec103 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2496,14 +2496,15 @@ const char* GuiControl::evaluate( const char* str ) { smThisControl = this; StringTableEntry objectName = getName(); - if (getName() == NULL) - objectName = getInternalName(); - StringTableEntry fileName = getFilename(); - if (fileName != NULL) - fileName = Platform::makeRelativePathName(fileName, NULL); + if (objectName != NULL) + objectName = getIdString(); - String context = String::ToString("%s\nObject: %s", fileName, objectName); - const char* result = Con::evaluate(str, false, context).value; + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + const char* result = Con::evaluate(str, false, context.c_str()).value; smThisControl = NULL; return result; From 001468cb5e894def09334475697292719a2ab5d9 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 2 Mar 2026 17:08:12 -0600 Subject: [PATCH 4/4] tone down overcorrection --- Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl | 2 +- Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl index a1df93c70..addc16541 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl @@ -243,7 +243,7 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; vec3 specularBRDF = numerator / denominator; - vec3 diffuseBRDF = surface.baseColor.rgb * surface.ao * M_PI_F; + vec3 diffuseBRDF = surface.baseColor.rgb * surface.ao * M_HALFPI_F; // Final output combining all terms vec3 kS = F; // Specular reflectance diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index 015c925bf..8b544ca9c 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -243,7 +243,7 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; float3 specularBRDF = numerator / denominator; - float3 diffuseBRDF = surface.baseColor.rgb * surface.ao* M_PI_F; + float3 diffuseBRDF = surface.baseColor.rgb * surface.ao* M_HALFPI_F; // Final output combining all terms float3 kS = F; // Specular reflectance