From 585a2c5a71f119496746cb121188be8ca5973e76 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 30 Aug 2026 11:46:39 +0200 Subject: [PATCH] =?UTF-8?q?Getting=20opendf=20building=20and=20rendering?= =?UTF-8?q?=20on=20macOS=20is=20done=20=E2=80=94=20Daggerfall=20paints=20v?= =?UTF-8?q?ia=20legacy=20GL=202.1=20+=20`#version=20120`=20shaders=20+=20M?= =?UTF-8?q?yGUI=20FetchContent=20+=20BGR/BGRA=20texture=20fallback.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 51 +++++++++++++++++++++- data/shaders/combiner.frag | 8 ++-- data/shaders/combiner.vert | 13 ++---- data/shaders/dir_light.frag | 12 +++-- data/shaders/dir_light.vert | 13 ++---- data/shaders/object.frag | 31 ++++++------- data/shaders/object.vert | 36 ++++++--------- data/shaders/quad_rect.frag | 8 ++-- data/shaders/quad_rect.vert | 13 ++---- data/shaders/quad_ui.frag | 10 ++--- data/shaders/quad_ui.vert | 18 +++----- data/shaders/sprite.frag | 31 ++++++------- data/shaders/sprite.vert | 38 +++++++--------- data/shaders/terrain.frag | 32 +++++++------- data/shaders/terrain.vert | 37 +++++++--------- docs/ROADMAP.md | 36 +++++++++++++++ src/components/mygui_osg/rendermanager.cpp | 24 +++------- src/components/mygui_osg/texture.cpp | 9 +++- src/opendf/engine.cpp | 6 +++ 19 files changed, 227 insertions(+), 199 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b307a2..2afd05c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,56 @@ endif() find_package(OpenSceneGraph REQUIRED osgDB osgViewer osgGA osgUtil) find_package(SDL2 REQUIRED) find_package(OpenGL REQUIRED) -find_package(MyGUI REQUIRED) + +# MyGUI isn't in Homebrew any more, so on macOS a fresh checkout has nothing +# for FindMyGUI to locate. AUTO tries the system first and falls back to +# FetchContent when nothing turns up; ON skips the search and always fetches; +# OFF keeps the old behaviour and errors out if MyGUI isn't installed. +set(OPENDF_FETCH_MYGUI AUTO CACHE STRING + "Fetch and build MyGUI in-tree when not found (ON/OFF/AUTO)") +set_property(CACHE OPENDF_FETCH_MYGUI PROPERTY STRINGS AUTO ON OFF) + +if(NOT OPENDF_FETCH_MYGUI STREQUAL "ON") + if(OPENDF_FETCH_MYGUI STREQUAL "OFF") + find_package(MyGUI REQUIRED) + else() + find_package(MyGUI QUIET) + endif() +endif() + +if(NOT MyGUI_FOUND) + message(STATUS "MyGUI not found -- fetching MyGUI 3.4.4 in-tree") + include(FetchContent) + # Matches the macOS CI build exactly: only MyGUIEngine, dummy render + # platform, no obsolete delegates. Forced into the cache because MyGUI's + # own CMake reads these before we add_subdirectory it, and because our + # AUTO detection below has to see MYGUI_DONT_USE_OBSOLETE=ON so the + # library and opendf agree about widget layout. + set(MYGUI_RENDERSYSTEM 1 CACHE STRING "" FORCE) # 1 = Dummy, the smallest platform (0 isn't a valid value) + set(MYGUI_DONT_USE_OBSOLETE ON CACHE BOOL "" FORCE) + set(MYGUI_DISABLE_PLUGINS TRUE CACHE BOOL "" FORCE) # skips the whole Plugins tree + foreach(_opt DEMOS TOOLS PLUGINS DOCS UNITTESTS TEST_APP WRAPPER) + set(MYGUI_BUILD_${_opt} OFF CACHE BOOL "" FORCE) + endforeach() + FetchContent_Declare(mygui + GIT_REPOSITORY https://github.com/MyGUI/mygui.git + GIT_TAG MyGUI3.4.4 + GIT_SHALLOW TRUE + ) + FetchContent_MakeAvailable(mygui) + # opendf includes MyGUI as , which only exists once + # MyGUI is installed. The in-tree layout is MyGUIEngine/include/MyGUI_Foo.h + # (flat, no MYGUI/ prefix), so synthesize the prefix with a symlink and + # point the include dir at its parent. + file(MAKE_DIRECTORY "${mygui_BINARY_DIR}/opendf-include-shim") + file(CREATE_LINK + "${mygui_SOURCE_DIR}/MyGUIEngine/include" + "${mygui_BINARY_DIR}/opendf-include-shim/MYGUI" + SYMBOLIC COPY_ON_ERROR) + set(MyGUI_LIBRARIES MyGUIEngine) + set(MyGUI_INCLUDE_DIRS "${mygui_BINARY_DIR}/opendf-include-shim") + set(MyGUI_FOUND TRUE) +endif() # MyGUI's EventPair is either a CompositeEvent (obsolete delegates enabled) or a # bare Event, depending on MYGUI_DONT_USE_OBSOLETE. That choice changes the layout diff --git a/data/shaders/combiner.frag b/data/shaders/combiner.frag index 33692b6..a79587c 100644 --- a/data/shaders/combiner.frag +++ b/data/shaders/combiner.frag @@ -1,13 +1,11 @@ -#version 130 +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect ColorTex; uniform sampler2DRect DiffuseTex; uniform sampler2DRect SpecularTex; -in vec4 TexCoord0; - -out vec4 ColorOutput; +varying vec4 TexCoord0; void main() { @@ -15,5 +13,5 @@ void main() vec3 diffuse = texture2DRect(DiffuseTex, TexCoord0.xy).rgb; vec3 specular = texture2DRect(SpecularTex, TexCoord0.xy).rgb; - ColorOutput = vec4(color*diffuse + specular, 1.0); + gl_FragColor = vec4(color*diffuse + specular, 1.0); } diff --git a/data/shaders/combiner.vert b/data/shaders/combiner.vert index e3a4bd8..39f6d54 100644 --- a/data/shaders/combiner.vert +++ b/data/shaders/combiner.vert @@ -1,14 +1,9 @@ -#version 130 +#version 120 -uniform mat4 osg_ProjectionMatrix; - -in vec4 osg_Vertex; -in vec4 osg_MultiTexCoord0; - -out vec4 TexCoord0; +varying vec4 TexCoord0; void main() { - gl_Position = osg_ProjectionMatrix * osg_Vertex; - TexCoord0 = osg_MultiTexCoord0; + gl_Position = gl_ProjectionMatrix * gl_Vertex; + TexCoord0 = gl_MultiTexCoord0; } diff --git a/data/shaders/dir_light.frag b/data/shaders/dir_light.frag index 610941d..99a0647 100644 --- a/data/shaders/dir_light.frag +++ b/data/shaders/dir_light.frag @@ -1,7 +1,8 @@ -#version 130 +#version 120 #extension GL_ARB_texture_rectangle : enable +#extension GL_ARB_draw_buffers : require -in vec3 localLightDir; +varying vec3 localLightDir; uniform vec4 ambient_color; uniform vec4 diffuse_color; @@ -11,9 +12,6 @@ uniform sampler2DRect ColorTex; uniform sampler2DRect NormalTex; uniform sampler2DRect PosTex; -out vec4 DiffuseData; -out vec4 SpecularData; - void main() { vec4 c_viewspace = texture2DRect(ColorTex, gl_FragCoord.xy); @@ -37,6 +35,6 @@ void main() float amount = max(0.0, dot(h_viewspace, n_viewspace)); vec3 spec = specular_color.rgb * s_viewspace * pow(amount, 32.0) * c_viewspace.a; - DiffuseData = vec4(diff, 1.0); - SpecularData = vec4(spec, 1.0); + gl_FragData[0] = vec4(diff, 1.0); + gl_FragData[1] = vec4(spec, 1.0); } diff --git a/data/shaders/dir_light.vert b/data/shaders/dir_light.vert index 317193a..2eb3f16 100644 --- a/data/shaders/dir_light.vert +++ b/data/shaders/dir_light.vert @@ -1,18 +1,13 @@ -#version 130 - -uniform mat4 osg_ProjectionMatrix; -uniform mat4 osg_ModelViewMatrix; +#version 120 uniform vec3 light_direction; -in vec4 osg_Vertex; - -out vec3 localLightDir; +varying vec3 localLightDir; void main() { - localLightDir = mat3(osg_ModelViewMatrix) * light_direction; + localLightDir = mat3(gl_ModelViewMatrix) * light_direction; // Vertex position in main camera Screen space. - gl_Position = osg_ProjectionMatrix * osg_Vertex; + gl_Position = gl_ProjectionMatrix * gl_Vertex; } diff --git a/data/shaders/object.frag b/data/shaders/object.frag index 5d03ea7..cf828fa 100644 --- a/data/shaders/object.frag +++ b/data/shaders/object.frag @@ -1,32 +1,29 @@ -#version 130 +#version 120 +#extension GL_EXT_texture_array : require +#extension GL_ARB_draw_buffers : require uniform vec4 illumination_color; uniform sampler2DArray diffuseTex; -in vec3 pos_viewspace; -in vec3 n_viewspace; -in vec3 t_viewspace; -in vec3 b_viewspace; -in vec4 TexCoords; -in vec4 Color; - -out vec4 ColorData; -out vec4 NormalData; -out vec4 PositionData; -out vec4 IlluminationData; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +varying vec4 Color; void main() { - vec4 color = vec4(texture(diffuseTex, TexCoords.xyz).rgb, 0.0); + vec4 color = vec4(texture2DArray(diffuseTex, TexCoords.xyz).rgb, 0.0); vec4 nn = vec4(0.5, 0.5, 1.0, 1.0); mat3 nmat = mat3(normalize(t_viewspace), normalize(b_viewspace), normalize(n_viewspace)); - ColorData = color * vec4(Color.rgb, 1.0); - NormalData = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); - PositionData = vec4(pos_viewspace, gl_FragCoord.z); - IlluminationData = illumination_color; + gl_FragData[0] = color * vec4(Color.rgb, 1.0); + gl_FragData[1] = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); + gl_FragData[2] = vec4(pos_viewspace, gl_FragCoord.z); + gl_FragData[3] = illumination_color; } diff --git a/data/shaders/object.vert b/data/shaders/object.vert index c7167dd..1f4a5bf 100644 --- a/data/shaders/object.vert +++ b/data/shaders/object.vert @@ -1,30 +1,22 @@ -#version 130 +#version 120 -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat4 osg_ModelViewMatrix; - -in vec4 osg_Vertex; -in vec3 osg_Normal; -in vec3 osg_MultiTexCoord1; // Binormal -in vec4 osg_Color; -in vec4 osg_MultiTexCoord0; - -out vec3 pos_viewspace; -out vec3 n_viewspace; -out vec3 t_viewspace; -out vec3 b_viewspace; -out vec4 TexCoords; -out vec4 Color; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +varying vec4 Color; void main() { - gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; - TexCoords = osg_MultiTexCoord0; - Color = osg_Color; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + TexCoords = gl_MultiTexCoord0; + Color = gl_Color; - pos_viewspace = (osg_ModelViewMatrix * osg_Vertex).xyz; + pos_viewspace = (gl_ModelViewMatrix * gl_Vertex).xyz; - n_viewspace = normalize(mat3(osg_ModelViewMatrix) * osg_Normal); - b_viewspace = normalize(mat3(osg_ModelViewMatrix) * osg_MultiTexCoord1); + n_viewspace = normalize(gl_NormalMatrix * gl_Normal); + // meshmanager packs the binormal into texcoord unit 1 (see setTexCoordArray(1, ...)) + b_viewspace = normalize(mat3(gl_ModelViewMatrix) * gl_MultiTexCoord1.xyz); t_viewspace = cross(n_viewspace, b_viewspace); } diff --git a/data/shaders/quad_rect.frag b/data/shaders/quad_rect.frag index c01c82a..2f1ab37 100644 --- a/data/shaders/quad_rect.frag +++ b/data/shaders/quad_rect.frag @@ -1,13 +1,11 @@ -#version 130 +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect TexImage; -in vec4 TexCoord0; - -out vec4 ColorOutput; +varying vec4 TexCoord0; void main() { - ColorOutput = texture2DRect(TexImage, TexCoord0.xy); + gl_FragColor = texture2DRect(TexImage, TexCoord0.xy); } diff --git a/data/shaders/quad_rect.vert b/data/shaders/quad_rect.vert index e3a4bd8..39f6d54 100644 --- a/data/shaders/quad_rect.vert +++ b/data/shaders/quad_rect.vert @@ -1,14 +1,9 @@ -#version 130 +#version 120 -uniform mat4 osg_ProjectionMatrix; - -in vec4 osg_Vertex; -in vec4 osg_MultiTexCoord0; - -out vec4 TexCoord0; +varying vec4 TexCoord0; void main() { - gl_Position = osg_ProjectionMatrix * osg_Vertex; - TexCoord0 = osg_MultiTexCoord0; + gl_Position = gl_ProjectionMatrix * gl_Vertex; + TexCoord0 = gl_MultiTexCoord0; } diff --git a/data/shaders/quad_ui.frag b/data/shaders/quad_ui.frag index 6432dec..f047b68 100644 --- a/data/shaders/quad_ui.frag +++ b/data/shaders/quad_ui.frag @@ -1,13 +1,11 @@ -#version 130 +#version 120 uniform sampler2D TexImage; -in vec4 Color; -in vec4 TexCoord0; - -out vec4 ColorOutput; +varying vec4 Color; +varying vec4 TexCoord0; void main() { - ColorOutput = texture2D(TexImage, TexCoord0.xy) * Color; + gl_FragColor = texture2D(TexImage, TexCoord0.xy) * Color; } diff --git a/data/shaders/quad_ui.vert b/data/shaders/quad_ui.vert index dbda982..4c48642 100644 --- a/data/shaders/quad_ui.vert +++ b/data/shaders/quad_ui.vert @@ -1,17 +1,11 @@ -#version 130 +#version 120 -uniform mat4 osg_ProjectionMatrix; - -in vec4 osg_Vertex; -in vec4 osg_Color; -in vec4 osg_MultiTexCoord0; - -out vec4 Color; -out vec4 TexCoord0; +varying vec4 Color; +varying vec4 TexCoord0; void main() { - gl_Position = osg_ProjectionMatrix * osg_Vertex; - TexCoord0 = osg_MultiTexCoord0; - Color = osg_Color; + gl_Position = gl_ProjectionMatrix * gl_Vertex; + TexCoord0 = gl_MultiTexCoord0; + Color = gl_Color; } diff --git a/data/shaders/sprite.frag b/data/shaders/sprite.frag index f3411c3..e4f62ab 100644 --- a/data/shaders/sprite.frag +++ b/data/shaders/sprite.frag @@ -1,24 +1,21 @@ -#version 130 +#version 120 +#extension GL_EXT_texture_array : require +#extension GL_ARB_draw_buffers : require uniform vec4 illumination_color; uniform sampler2DArray diffuseTex; -in vec3 pos_viewspace; -in vec3 n_viewspace; -in vec3 t_viewspace; -in vec3 b_viewspace; -in vec4 TexCoords; -in vec4 Color; - -out vec4 ColorData; -out vec4 NormalData; -out vec4 PositionData; -out vec4 IlluminationData; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +varying vec4 Color; void main() { - vec4 color = texture(diffuseTex, TexCoords.xyz); + vec4 color = texture2DArray(diffuseTex, TexCoords.xyz); color.a = ((color.a < 0.5) ? 1.0 : 0.0); vec4 nn = vec4(0.5, 0.5, 1.0, 1.0); @@ -26,8 +23,8 @@ void main() normalize(b_viewspace), normalize(n_viewspace)); - ColorData = color * vec4(Color.rgb, 1.0); - NormalData = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); - PositionData = vec4(pos_viewspace, gl_FragCoord.z); - IlluminationData = illumination_color; + gl_FragData[0] = color * vec4(Color.rgb, 1.0); + gl_FragData[1] = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); + gl_FragData[2] = vec4(pos_viewspace, gl_FragCoord.z); + gl_FragData[3] = illumination_color; } diff --git a/data/shaders/sprite.vert b/data/shaders/sprite.vert index 2f61c5c..65ec1ba 100644 --- a/data/shaders/sprite.vert +++ b/data/shaders/sprite.vert @@ -1,33 +1,25 @@ -#version 130 - -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat4 osg_ModelViewMatrix; +#version 120 uniform float CurrentFrame; -in vec4 osg_Vertex; -in vec3 osg_Normal; -in vec4 osg_Color; -in vec4 osg_MultiTexCoord0; - -out vec3 pos_viewspace; -out vec3 n_viewspace; -out vec3 t_viewspace; -out vec3 b_viewspace; -out vec4 TexCoords; -out vec4 Color; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +varying vec4 Color; void main() { - gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; - TexCoords = osg_MultiTexCoord0; + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + TexCoords = gl_MultiTexCoord0; TexCoords.z += CurrentFrame; - Color = osg_Color; + Color = gl_Color; - pos_viewspace = (osg_ModelViewMatrix * osg_Vertex).xyz; + pos_viewspace = (gl_ModelViewMatrix * gl_Vertex).xyz; - vec3 binormal = cross(osg_Normal, vec3(1.0, 0.0, 0.0)); - n_viewspace = normalize(mat3(osg_ModelViewMatrix) * osg_Normal); - t_viewspace = normalize(mat3(osg_ModelViewMatrix) * cross(osg_Normal, binormal)); - b_viewspace = normalize(mat3(osg_ModelViewMatrix) * binormal); + vec3 binormal = cross(gl_Normal, vec3(1.0, 0.0, 0.0)); + n_viewspace = normalize(gl_NormalMatrix * gl_Normal); + t_viewspace = normalize(mat3(gl_ModelViewMatrix) * cross(gl_Normal, binormal)); + b_viewspace = normalize(mat3(gl_ModelViewMatrix) * binormal); } diff --git a/data/shaders/terrain.frag b/data/shaders/terrain.frag index 3d9d93f..2c64293 100644 --- a/data/shaders/terrain.frag +++ b/data/shaders/terrain.frag @@ -1,33 +1,31 @@ -#version 130 +#version 120 +#extension GL_EXT_texture_array : require +#extension GL_EXT_gpu_shader4 : require +#extension GL_ARB_draw_buffers : require uniform vec4 illumination_color; uniform sampler2DArray diffuseTex; -in vec3 pos_viewspace; -in vec3 n_viewspace; -in vec3 t_viewspace; -in vec3 b_viewspace; -in vec4 TexCoords; -flat in uint TexIndex; - -out vec4 ColorData; -out vec4 NormalData; -out vec4 PositionData; -out vec4 IlluminationData; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +flat varying uint TexIndex; void main() { vec3 coord = vec3(TexCoords.xy, float(TexIndex)); - vec4 color = vec4(texture(diffuseTex, coord).rgb, 0.0); + vec4 color = vec4(texture2DArray(diffuseTex, coord).rgb, 0.0); vec4 nn = vec4(0.5, 0.5, 1.0, 1.0); mat3 nmat = mat3(normalize(t_viewspace), normalize(b_viewspace), normalize(n_viewspace)); - ColorData = color; - NormalData = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); - PositionData = vec4(pos_viewspace, gl_FragCoord.z); - IlluminationData = illumination_color; + gl_FragData[0] = color; + gl_FragData[1] = vec4(nmat*(nn.xyz - vec3(0.5)) + vec3(0.5), nn.w); + gl_FragData[2] = vec4(pos_viewspace, gl_FragCoord.z); + gl_FragData[3] = illumination_color; } diff --git a/data/shaders/terrain.vert b/data/shaders/terrain.vert index c6d1524..5db11c6 100644 --- a/data/shaders/terrain.vert +++ b/data/shaders/terrain.vert @@ -1,36 +1,31 @@ -#version 130 +#version 120 +#extension GL_EXT_gpu_shader4 : require #extension GL_ARB_draw_instanced : enable -uniform mat4 osg_ModelViewProjectionMatrix; -uniform mat4 osg_ModelViewMatrix; - uniform usampler2D tilemapTex; -in vec4 osg_Vertex; -in vec4 osg_MultiTexCoord0; - -out vec3 pos_viewspace; -out vec3 n_viewspace; -out vec3 t_viewspace; -out vec3 b_viewspace; -out vec4 TexCoords; -flat out uint TexIndex; +varying vec3 pos_viewspace; +varying vec3 n_viewspace; +varying vec3 t_viewspace; +varying vec3 b_viewspace; +varying vec4 TexCoords; +flat varying uint TexIndex; void main() { int x = gl_InstanceIDARB & 15; int y = gl_InstanceIDARB / 16; - vec4 pos = osg_Vertex + vec4(x*256, 0, y*-256, 0); + vec4 pos = gl_Vertex + vec4(x*256, 0, y*-256, 0); - gl_Position = osg_ModelViewProjectionMatrix * pos; - TexCoords = osg_MultiTexCoord0; - TexIndex = texelFetch(tilemapTex, ivec2(x, y), 0).r; + gl_Position = gl_ModelViewProjectionMatrix * pos; + TexCoords = gl_MultiTexCoord0; + TexIndex = texelFetch2D(tilemapTex, ivec2(x, y), 0).r; - pos_viewspace = (osg_ModelViewMatrix * pos).xyz; + pos_viewspace = (gl_ModelViewMatrix * pos).xyz; vec3 normal = vec3(0.0, -1.0, 0.0); vec3 binormal = vec3(1.0, 0.0, 0.0); - n_viewspace = normalize(mat3(osg_ModelViewMatrix) * normal); - t_viewspace = normalize(mat3(osg_ModelViewMatrix) * cross(normal, binormal)); - b_viewspace = normalize(mat3(osg_ModelViewMatrix) * binormal); + n_viewspace = normalize(gl_NormalMatrix * normal); + t_viewspace = normalize(mat3(gl_ModelViewMatrix) * cross(normal, binormal)); + b_viewspace = normalize(mat3(gl_ModelViewMatrix) * binormal); } diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index d72c51c..6c80312 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -142,6 +142,42 @@ So the GUI and windowing arguments against moving have largely gone away; the pipeline and the shaders are what is left, and they are a rewrite of the rendering half of the project. +macOS is a further nudge in the same direction. Apple deprecated OpenGL in +10.14 and caps the legacy context at 2.1, so opendf's shaders are pinned at +`#version 120` there. VSG on macOS runs Vulkan through +[MoltenVK](https://github.com/KhronosGroup/MoltenVK), which sits on Metal -- +the API Apple is actually maintaining -- so a VSG migration would replace +the 2.1 pin with a modern backend on every platform at once. + +We tried a 3.3 Core context on macOS first (SDL context request + OSG traits ++ Program aliasing overrides + explicit attribute binding + `#version 330 +core` shaders and MRT `layout(location = N)`) and every screen-facing draw +came out black. Debugging it produced the `OPENDF_GL_DIAG` harness -- a +self-contained `osg::Drawable` that bypassed OSG entirely, managing its own +program, VAO and VBO through raw `SDL_GL_GetProcAddress` entry points and +logging `glGetError` at every step. It rendered a magenta fullscreen +triangle on macOS 26 / Apple Silicon (M5 Pro, GL 4.1 Core) with zero GL +errors, which proved the Core context, the shader work and Cocoa surface +presentation were all fine; the failure was inside OSG 3.6.5's +`Geometry::drawImplementation` under Core, which silently drops draws for +its own `osg::Geometry` objects. Anything we drove manually paints; anything +OSG orchestrates (deferred pipeline screen quads, the MyGUI backend, scene +meshes) came out empty. OpenMW hits the same wall and short-circuits it in +`components/shader/shadermanager.cpp` with `templateName = "compatibility/" ++ templateName;` and the comment "until core support is supported". + +So opendf on macOS is now on legacy 2.1 with `#version 120` shaders and +OSG-orchestrated draws, matching OpenMW. The harness has been deleted now +that it has delivered its verdict -- it was dead code in `pipeline.cpp` +behind an off-by-default `#define`, and on legacy 2.1 it only reconfirms +what already renders. Resurrect it from git history if a Core context or +the VSG port is ever retried; it was last seen working (GLSL 120 and 330 +core, VAO optional, centre-pixel readback) just before its removal. It also +transposes cleanly into a `GL_KHR_debug` callback on drivers that expose it +(macOS Core does not) -- rename `drawImplementation` into a +`glDebugMessageCallback` handler and log the message text instead of +`glGetError`. + Two things make this cheaper whenever it happens, and are worth doing anyway: keep rendering behind the `render/` seam so `world/` and `class/` do not reach for `osg::` directly, and keep shaders as external data files (they already diff --git a/src/components/mygui_osg/rendermanager.cpp b/src/components/mygui_osg/rendermanager.cpp index 62b6ca6..dcb7fd0 100644 --- a/src/components/mygui_osg/rendermanager.cpp +++ b/src/components/mygui_osg/rendermanager.cpp @@ -70,24 +70,12 @@ class ResizeHandler : public osgGA::GUIEventHandler { osg::StateSet *setShaderProgram(osg::Node *node, const std::string &vert, const std::string &frag) { osg::StateSet *ss = node->getOrCreateStateSet(); - if(1) - { - osg::ref_ptr program = new osg::Program(); - program->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, vert)); - program->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, frag)); - - ss->setAttributeAndModes(program.get(), - osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE - ); - } - else - { - osg::ref_ptr mat(new osg::Material()); - mat->setColorMode(osg::Material::OFF); - ss->setAttributeAndModes(mat, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); - ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); - ss->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - } + osg::ref_ptr program = new osg::Program(); + program->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, vert)); + program->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, frag)); + ss->setAttributeAndModes(program.get(), + osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE + ); return ss; } diff --git a/src/components/mygui_osg/texture.cpp b/src/components/mygui_osg/texture.cpp index 8312934..9d344f9 100644 --- a/src/components/mygui_osg/texture.cpp +++ b/src/components/mygui_osg/texture.cpp @@ -1,6 +1,7 @@ #include "texture.h" +#include #include #include @@ -102,16 +103,22 @@ void Texture::loadFromFile(const std::string &fname) numelems = 2; break; case GL_RGB: + case GL_BGR: format = MyGUI::PixelFormat::R8G8B8; numelems = 3; break; case GL_RGBA: + case GL_BGRA: format = MyGUI::PixelFormat::R8G8B8A8; numelems = 4; break; default: - throw std::runtime_error("Unsupported pixel format"); + { + char buf[16]; + std::snprintf(buf, sizeof(buf), "0x%x", image->getPixelFormat()); + throw std::runtime_error(std::string("Unsupported pixel format ") + buf); + } } image->flipVertical(); diff --git a/src/opendf/engine.cpp b/src/opendf/engine.cpp index 98802c8..889acbf 100644 --- a/src/opendf/engine.cpp +++ b/src/opendf/engine.cpp @@ -423,6 +423,12 @@ bool Engine::go(void) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + // No Core request on macOS: OSG 3.6.5's Geometry::drawImplementation + // silently drops draws under a Core context (proven with a + // bypass-OSG harness; see docs/ROADMAP.md), so we stay on Cocoa's + // legacy 2.1 profile and use #version 120 shaders. OpenMW ships the + // same workaround -- see components/shader/shadermanager.cpp:515. + Log::get().stream()<< "Creating window "<