Win64, LCL, simple shapes - something got broken


I wanted to make a simple demo about rounding errors…
…and suddenly, after git pull, saw my demo and then my app rendering nothing. Scaaary.

Okay, the rendering is back again at

Ревизия: f3f70782eb8c56e1e159db395c9f879059b4c7e1
Автор: Michalis Kamburelis [email protected]
Дата: 06.02.2022 6:33:17
Mention load_model_and_camera_manually is deliberately by code

The rendering is totally lost (nothing but background color) on today fetch. (3.4 KB)

2022-05-01 19_40_12-В синем море... 2022-05-01 19_40_02-В синем море...

If rendering something at all :slight_smile: then by pressing left/right arrows you would be moving top grey shape.
And the rendering is not stable. The distance between leftmost triangle (cone) and the main body (cylinder or box) keeps varying on one pixel. Seems rounding is done differently one rotated elementary shapes, together making the shape.
Yet more weird is how the “bottom right” line of the rightmost cone keeps appearing and disappearing, but not the “top right” one! The movement is horizontal, so there should not be any jitter along the vertical axis.

Perhaps the rounding can be applied AFTER rotation, so the rounding errors would be the same over all the nodes?

Perhaps there can be some utility function that “fuses” a given shape with children, bringing all the inner nodes into the same flat array without nesting? This however would need destroying child components, which is dangerous of dangling pointers, or would need to turn children into hollow placeholders having zero nodes inside.

Maybe there is(was) something simple to make “antialiased” rendering that would conceal rounding errors but i failed to find it.
Keep right arrow pressed - and you would see the shape on the move distorted back-and-forth.

The idea was to keep coordinates in real world meters, so the numbers are quite large, but you said it was okay, there is no pre-fixed distance units in the engine.

Anyway, after upgrading to the latest engine - nothing is rendered at all :-/

procedure TfmSea.FormCreate(Sender: TObject);

procedure TfmSea.CreateScene;
var ShipN: TCastleTransform; i: integer;
  Viewport := TCastleViewport.Create(Self);
  Viewport.FullSize := true;                               
  Viewport.Camera.Orthographic.Width := 2000 * pxInMeter;
  Viewport.Camera.Orthographic.Height := 2000 * pxInMeter;
  Viewport.Camera.Orthographic.Origin := Vector2(0.5, 0.5);
  Viewport.Camera.ProjectionNear := -50000;
  Viewport.Camera.ProjectionFar := +50000;

  Viewport.BackgroundColor := Navy;


  Ship1 := CreateShip1(Self, Vector4(0.2, 0.75, 0.75, 1), Teal);
  Ship2 := CreateShip2(Self, Silver, Black);

  Ship1.TranslationXY := Vector2(-5000, 0);
  Ship2.TranslationXY := Vector2(-1500, +7500);
  Ship2.Rotation := Vector4(0, 0, 1, - pi /2 );


  for i := 1 to 10 do begin
    ShipN := CreateShip2(Self, Teal, Blue);
    ShipN.TranslationXY := Vector2(-1500 + i * pxInMeter, +7000 - pxInMeter * i * 40 );
    ShipN.Rotation := Vector4(0, 0, 1, - pi /2 );

function CreateShip2(const Owner: TComponent; const color, colorMark: TCastleColor
  ): TCastleTransform;
  cf, cr: TCastleCone;
  a: TCastlePlane; // TCastleCylinder;
  b: TCastleBox;

  L, W: integer;

  procedure Setup1(const O: TCastleAbstractPrimitive);
    O.Material := pmUnlit;
    O.Color := color;

//    O.RenderOptions.Blending := True;
//    O.RenderOptions.BlendingSort := bs2D;
  Result := TCastleTransform.Create(Owner);

  L := round(40 * pxInMeter);
  W := round(15 * pxInMeter);

  b := TCastleBox.Create(Owner);
  a := TCastlePlane.Create(Owner);
  cf := TCastleCone.Create(Owner);
  cr := TCastleCone.Create(Owner);


  //b.Height := L;
  //b.Radius := W;
  b.Size := Vector3(W*2, L, 2);

//  a.Height := 3.5 * pxInMeter;
//  a.Radius := 3.5 * pxInMeter;
  a.Size := Vector2( 3 * pxInMeter, 2 * pxInMeter);
  a.Axis := 2;
  a.Material := pmUnlit;
  a.Color := colorMark;

  cf.BottomRadius := W;
  cf.Height := W;
  cr.BottomRadius := W;
  cr.Height := W;

  cf.TranslationXY := Vector2(0, -(L+W)/2);
  cr.TranslationXY := Vector2(0, +(L+W)/2);
  a.Translation    := Vector3(0, 0, 2*W);


Testing on my side – it works fine for me. Using latest CGE master, 502db458ad1d631e6f5b107bc41d2ed786cc9946 right now, as of today.

Tested on Linux/x86_64 and Windows/x86_64 (Windows 10). Both using Lazarus 2.2 and FPC 3.2.2.

Rendering is OK, moving with left/right works fine for me.

So, we need more information:

  1. What is your Lazarus, FPC version?

  2. Please send the OpenGL report of your system, in case your GPU has some non-standard set of features/problems. Use the “Help → System Information” from the CGE editor, click there to save the whole report to file, attach it here.

  3. Does the only thing that change betwen your 2 tests (you report that latest CGE master fails, but f3f70782eb8c56e1e159db395c9f879059b4c7e1 works) is the CGE version? Did you test them both on the same FPC, Lazarus etc., on exactly the same system, with the same drivers etc.?

  4. Unless there’s some easy conclusion from your answers to AD 1 - AD 3, I may ask you to just do bisection, and locate where exactly do the trouble occur. There were a number of changes in the last ~3 months (since f3f70782eb8c56e1e159db395c9f879059b4c7e1) but nothing that obviously connects with my mind with what you’re doing.

The code looks OK, you create a number of TCastleTransform descendants, with unlit material, and move them. I don’t see there anything that could break because of some CGE change.

You render meshes that are very small (in final screen pixels). So the aliasing occurs. This is normal (in every rendering engine).

  • The easiest way to deal with it is to use full-screen anti-aliasing.

    In case of TCastleControl, just set TCastleControl.MultiSampling to e.g. 4. (In case of TCastledWindow, there’s equivalent TCastleWindow.MultiSampling or a bit higher-level TCastleWindow.AntiAliasing.)

    Note that not all GPUs in the world may support it, older GPUs will revert to no-anti-aliasing (but 4 should be, practically, supported ~everywhere now).

  • Another approach would be to render each ship as an image, instead of geometry. Then various texture filtering modes can essentially deal with aliasing too. But this would be a larger rework, and would prevent the ships from being customizable (each part existing or not, possibly transformed separately etc.) so you probably don’t want to go into this direction.

As for any weirdness: as I say, we just pass these things to OpenGL. Maybe some weird behavior is caused by large numbers (unlimately they are multiplied on GPU).

The “rounding” is just standard OpenGL rasterization in this case, not even controlled by the engine. The OpenGL determines which pixels are hit by triangle rendering. This already happens after the vertexes have been transformed (by all transformations in 3D, and projected to screen space).

We have DynamicBatching that does what you seem to describe. It’s done at rendering, without reorganizing your data.

But it will likely not change anything in your case. You have aliasing. It is normal if you render geometries that are small (in pixels). Changing the way they are organized will not really cure it (though you may experience different artifacts due to different transformations being applied if you rearrange the hierarchy).

That is exactly TCastleControl.MultiSampling :slight_smile:

The devel box is integrated AMD/ATi video on Win7, but the “breathing” was also noticed on another box, with Intel integrated and Win10

I wonder if you have some integrated low-rank video boxes for tests or only expensive discrete videos? I think game devels would be naturally biased towards the latter.

Lazarus 2.2.0 (rev lazarus_2_2_0-160-g6ba333bd22) FPC 3.2.3 x86_64-win64-win32/win64

Use the “Help → System Information” from the CGE editor

Can you add it to Preferences so could be queried without creating fake project first?
Anyway… i’m lost.

2022-05-03 17_17_52-About

This is from one old program, not sure if helps: (7.2 KB)

3: sure.

4: i feared that :slight_smile: that would take a learning curve… And some spare time. So i hoped for some low-hanging fruit :smiley:

to render each ship as an image, instead of geometry.

would try multisampling, thanks for hint.

I expect that free rotations would be needed, so sprites do not seem that good of idea.
Fre zooming was nixed as unnecessary complication yet, but maybe would come back later.

I remade that code into GL 2D primitives and there are antialiazingg problems toom albeit less obvious. The only thing i thought that maybe GC does or can do all the coords normalization before passing them to GL drivers, but not sure that is worth it. I don’t know if real, not theoretical, videodrivers have problems with coordinates of 10^4 or 10^5 range, do not feel realyl large for modern computers, and especially for floating point numbers.

P.S. I wonder if something like porting SVG TCanvas to GL 2D primitives would make any sense, towards working on low-tech video cards if nothing else, comparing to managing full-flavor x3d nodes, especially for HUD-like uses where “virtual world” zooming should be ignored and the 2D physical screen should be anchor of object sizes instead.

I can snap Radeon 7700 into the box but would prefer not too :slight_smile:

Gave it a quick try;

With the demo, MS = 2 and MS = 4 produce different pictures, but MS = 8 seems (on a quick glance, can be wrong) render the same as MS = 0

Artifacts are different (with MS = 2 even curiously different), but still there.

I wonder if sub-pixel antialiasing can be enabled, something like Font rendering on WinXP and MaxOS ?

For a while i settled with MS = 4 and

//  DrawPrimitive2D(pmLineStrip, Hull, ColorHull);
//  DrawPrimitive2D(pmLineStrip, Hull, ColorHull, bsOne, bdZero, false, 1);
  DrawPrimitive2D(pmLineStrip, Hull, ColorHull, bsOne, bdZero, false, 2);

There still is a small inaccuracy, but it is less obvious (the tip and the very ends of lines)
2022-05-03 19_33_13-В синем море...
2022-05-03 19_33_02-В синем море...

My questions were targetted at resolving the problem you mentioned – “The rendering is totally lost (nothing but background color) on today fetch.”. So I’m interested whether you tested (both master and f3f70782eb8c56e1e159db395c9f879059b4c7e1) on the exactly same system with the same compiler etc. (and confirmed that master rendering is blank, while f3f70782eb8c56e1e159db395c9f879059b4c7e1 renders OK).

OK, from your later answer I understand this is “yes”.

Among me and all the contributors we likely have good coverage of everything. Most developers, myself included, don’t really have that “super-high-end gamer GPU” from what I know :slight_smile:

You show a screenshot from old CGE editor, that’s why “Help → System Information” is missing of course.

Thanks, but please still make a report using “Help → System Information”. I also want to know how CGE “sees” your GPU.

Note that sprites in TCastleScene can be rotated, like anything else descending from TCastleTransform.

That probably means your GPU doesn’t support MultiSampling = 8. LCL TOpenGLControl, on which TCastleControl is based, falls back to “no multisampling” in this case.

This is what multi-sampling (full-screen anti-aliasing) does.

i am trying bi-sect now

two major fears were

  1. i have that RotationAngle patch - irrelevant as i removed its use from the minimized demo

  2. i am not sure if ALL the commits are to be ocnsidered working, there could be ones with major malfunciton or even ones just used to “save temporary work” with no wattanty to even compile.

Okay, this latter can only be known by trial :slight_smile:

Note that sprites in TCastleScene can be rotated

sure, i took part in that rotating wheel topic :slight_smile:
but the quality would degrade, and the less details (‘noise’) and the less pixels (size) the sprite has - the more noticeable it would be. So i hope to avoid that avenue.

falls back to “no multisampling” in this case

thought so, did not bother to check

I wonder if sub-pixel antialiasing

this is what multi-sampling (full-screen anti-aliasing) does.

frankly, to me this did not look like that…

more correct: IF i used DrawPrimitive2D(pmLineStrip, Hull, ColorHull); there seemed to be subpixel antialiasing done badly. And if you fouce on my later screenshots, done with uncommented line with 2px wide lines, focus on the very very tip - i do not see there any half-drawn pixels, there either is one pixel on the very forward corner, or there is no and the “nose” is blunt.

granted, i did not do much testing, only what it looked on the first glance.

and this is dependent upon specific video driver, settings, and what not.

P.S. and that was one thing i feared too, one about Laz IDE being spoiled with Delphi…

Компиляция пакета castle_base 6.5: Код завершения 1, ошибок: 1
Fatal: Internal error 200611031

Perhaps i could use LazBuild instead of full-featured IDE but i am newb on the tooling.

Okay, going with clean-and-rebuild instead, works but sloooow.

…and here we go.

179b384d5bc0df3b88abf6f1575611666f9d0297 is the first bad commit
commit 179b384d5bc0df3b88abf6f1575611666f9d0297
Date:   Fri Mar 4 16:50:13 2022 +0100

Change PhongShading default to true, MaxLightsPerShape to 64

src/base/ | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)

Looks like we, just like wit hmultisampling, hit another GL driver/hardware limit.

Is there a way to query the value from real GL subsystem in runtime?

-      DefaultPhongShading = false;
-      DefaultMaxLightsPerShape = 8;
+      DefaultPhongShading = true;
+      DefaultMaxLightsPerShape = 64;

Need your help again…

I do this change to my demo…

  Viewport.BackgroundColor := Navy;

//  Viewport.Items.MainScene.RenderOptions.MaxLightsPerShape := 8;
//  Viewport.Items.MainScene.RenderOptions.PhongShading := False;


As long as i uncomment those lines - i get the AV at the starting of the app.

function TCastleScene.GetRenderOptions: TCastleRenderOptions;
  Result := Renderer.RenderOptions;

Where should i be overriding those default values then ?

  tmp1 := Viewport.Items;
  tmp2 := tmp1.MainScene;
  tmp3 := tmp2.RenderOptions;
  tmp3.MaxLightsPerShape := 8;
  tmp3.PhongShading := False;

MainScene seems nil no matter where i do it.

UPD 2. So it is all about Phong… Whenever i add/remove Setup1 calls - the element is appearing or disappearing

This is unrelated to this thread, it seems. Please stay on topic, don’t turn this into another thread where you ask about many unrelated things. The point of this thread is to find why do you experience the problem “The rendering is totally lost (nothing but background color)”.

As for MaxLightsPerShape, this value is not queried from OpenGL, as modern OpenGL essentially doesn’t have such limit. OK, there is a practical limit – which comes from the shader code complexity (so, depends on everything else the shader is doing), and also from the fact that too many light sources (if you actually use them) would slow down your rendering. So it’s not really something we can query. See Design lights using Castle Game Engine: new light components and related features, with video! – Castle Game Engine about it.

With older OpenGL (fixed-function pipeline) there is a hard limit, and indeed we query it. In case you use ancient GPU with ancient OpenGL fixed-function pipeline, we internally cap the actual limit by the OpenGL limit in this case.

MainScene is not automatically assigned by anything. You need to assign some scene to it, or it will be nil. (And it can actually stay nil, in many practical applications.)

it actually was very related

Hm. Weird. Of course, for unlit material – the Phong shading should not matter.

Please send the OpenGL report I asked for earlier. I’d like to see what CGE determined for your GPU.

I missed that comment “is the first bad commit”, sorry.

All right – we have a culprit. Thanks! Interesting. Please send the OpenGL report, I wonder if your OpenGL was detected to use some different rendering approach then usual?

recompiling all now, wait a bit :slight_smile:

back to “MainScene” - is there some other place i can suppress Phong once for all, some top-level render options when MainScene is nil ? Or is applying this to every single 3D object the only way for me in situations like this?

P.S. i still vote this would be immediately available from the starting screen, or from Preferences, without having to creating dummy project first.

GCE GL Summary

OpenGL information (detected by castle-editor):

Version string: 3.2.9606 Compatibility Profile Context
Version parsed: major: 3, minor: 2, release exists: True, release: 9606, vendor-specific information: “Compatibility Profile Context”
Vendor-specific version parsed: major: 0, minor: 0, release: 0
Vendor: ATI Technologies Inc.
Vendor type: ATI

Renderer: ATI Radeon HD 4250
Fglrx (ATI on Linux): False
Mesa: False

Buggy glGenerateMipmap(EXT): False
Buggy VBO: False
Buggy shader shadow map: False
Buggy FBO rendering to multi-sampling texture: False
Buggy FBO rendering to cube map texture: False
Buggy swap buffers with non-standard glViewport: False
Buggy 32-bit depth buffer: False
Buggy GLSL gl_FrontFacing: False
Buggy GLSL read varying: False
Buggy Pure Shader Pipeline: True
Buggy Texture Size Above 2048: False
Buggy Shader Bump Mapping num_steps: False

Real versions available:
(checks both version string and actual functions availability in GL library, to secure from buggy implementations)

1.2: True
1.3: True
1.4: True
1.5: True
2.0: True
2.1: True
3.0: True
3.1: True
3.2: False
3.3: False
4.0: False

Shaders (GLSL) support: Standard
=> Enable deprecated (fixed-function) support: True
Multi-texturing: True
Framebuffer Object: Standard (or ARB “core extension”)
Multi-sampling for FBO buffers and textures: True
Vertex Buffer Object: True
GenerateMipmap available (and reliable): True
Cube map textures: Standard
Compressed textures supported: [DXT1_RGB, DXT1_RGBA, DXT3, DXT5]
3D textures: Standard
Textures non-power-of-2: True
Blend constant parameter: True
Float textures: True
Depth textures: True
Packed depth + stencil: True

All extensions: GL_AMDX_name_gen_delete GL_AMD_draw_buffers_blend GL_AMD_performance_monitor GL_AMD_shader_stencil_export GL_ARB_color_buffer_float GL_ARB_copy_buffer GL_ARB_depth_buffer_float GL_ARB_depth_clamp GL_ARB_depth_texture GL_ARB_draw_buffers GL_ARB_draw_buffers_blend GL_ARB_draw_elements_base_vertex GL_ARB_draw_instanced GL_ARB_fragment_coord_conventions GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_fragment_shader GL_ARB_framebuffer_object GL_ARB_framebuffer_sRGB GL_ARB_geometry_shader4 GL_ARB_half_float_pixel GL_ARB_half_float_vertex GL_ARB_imaging GL_ARB_instanced_arrays GL_ARB_map_buffer_range GL_ARB_multisample GL_ARB_multitexture GL_ARB_occlusion_query GL_ARB_pixel_buffer_object GL_ARB_point_parameters GL_ARB_point_sprite GL_ARB_provoking_vertex GL_ARB_seamless_cube_map GL_ARB_shader_objects GL_ARB_shader_texture_lod GL_ARB_shading_language_100 GL_ARB_shadow GL_ARB_shadow_ambient GL_ARB_sync GL_ARB_texture_border_clamp GL_ARB_texture_buffer_object GL_ARB_texture_compression GL_ARB_texture_compression_rgtc GL_ARB_texture_cube_map GL_ARB_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar GL_ARB_texture_env_dot3 GL_ARB_texture_float GL_ARB_texture_mirrored_repeat GL_ARB_texture_multisample GL_ARB_texture_non_power_of_two GL_ARB_texture_rectangle GL_ARB_texture_rg GL_ARB_texture_snorm GL_ARB_transpose_matrix GL_ARB_uniform_buffer_object GL_ARB_vertex_array_bgra GL_ARB_vertex_array_object GL_ARB_vertex_buffer_object GL_ARB_vertex_program GL_ARB_vertex_shader GL_ARB_window_pos GL_ATI_draw_buffers GL_ATI_envmap_bumpmap GL_ATI_fragment_shader GL_ATI_meminfo GL_ATI_separate_stencil GL_ATI_texture_compression_3dc GL_ATI_texture_env_combine3 GL_ATI_texture_float GL_ATI_texture_mirror_once GL_EXT_abgr GL_EXT_bgra GL_EXT_bindable_uniform GL_EXT_blend_color GL_EXT_blend_equation_separate GL_EXT_blend_func_separate GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_compiled_vertex_array GL_EXT_copy_buffer GL_EXT_copy_texture GL_EXT_draw_buffers2 GL_EXT_draw_instanced GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_framebuffer_blit GL_EXT_framebuffer_multisample GL_EXT_framebuffer_object GL_EXT_framebuffer_sRGB GL_EXT_geometry_shader4 GL_EXT_gpu_program_parameters GL_EXT_gpu_shader4 GL_EXT_histogram GL_EXT_multi_draw_arrays GL_EXT_packed_depth_stencil GL_EXT_packed_float GL_EXT_packed_pixels GL_EXT_pixel_buffer_object GL_EXT_point_parameters GL_EXT_provoking_vertex GL_EXT_rescale_normal GL_EXT_secondary_color GL_EXT_separate_specular_color GL_EXT_shadow_funcs GL_EXT_stencil_wrap GL_EXT_subtexture GL_EXT_texgen_reflection GL_EXT_texture3D GL_EXT_texture_array GL_EXT_texture_buffer_object GL_EXT_texture_buffer_object_rgb32 GL_EXT_texture_compression_latc GL_EXT_texture_compression_rgtc GL_EXT_texture_compression_s3tc GL_EXT_texture_cube_map GL_EXT_texture_edge_clamp GL_EXT_texture_env_add GL_EXT_texture_env_combine GL_EXT_texture_env_dot3 GL_EXT_texture_filter_anisotropic GL_EXT_texture_integer GL_EXT_texture_lod GL_EXT_texture_lod_bias GL_EXT_texture_mirror_clamp GL_EXT_texture_object GL_EXT_texture_rectangle GL_EXT_texture_sRGB GL_EXT_texture_shared_exponent GL_EXT_texture_snorm GL_EXT_texture_swizzle GL_EXT_timer_query GL_EXT_transform_feedback GL_EXT_vertex_array GL_EXT_vertex_array_bgra GL_IBM_texture_mirrored_repeat GL_KTX_buffer_region GL_NV_blend_square GL_NV_conditional_render GL_NV_copy_depth_to_color GL_NV_explicit_multisample GL_NV_primitive_restart GL_NV_texgen_reflection GL_SGIS_generate_mipmap GL_SGIS_texture_edge_clamp GL_SGIS_texture_lod GL_SUN_multi_draw_arrays GL_WIN_swap_hint WGL_EXT_swap_control

Current buffers bit depths:
Color (red / green / blue / alpha): 8 / 8 / 8 / 8
Depth: 24
Index: 0
Stencil: 8
Accumulation (red / green / blue / alpha): 0 / 0 / 0 / 0
Double buffer: True
Multi-sampling (full-screen anti-aliasing) possible: True
Current: 1 samples per pixel

Stack depths:
Attributes: 16
Client attributes: 16
Modelview: 32
Projection: 10
Texture: 10
Name: 64

Max clip planes: 8
Max lights (fixed-function limit): 8
Max eval order: 40
Max list nesting: 64
Max pixel map table: 256
Max texture size: 8192
Max viewport dims (width, height): 8192 8192
Max texture units (shader pipeline): 16
Max texture units (fixed-function): 8
Max cube map texture size: 8192
Max 3d texture size: 8192
Max texture max anisotropy: 16
Query counter bits (for occlusion query): 32
Max renderbuffer size: 8192

Memory (in Kb):
Total: 0 (unknown)
Current: 0 (unknown)
Current for VBO: 229817
Current for Textures: 229817
Current for Renderbuffers: 229817

P.P.S. this is the chip - ATI Radeon HD 4250 Specs | TechPowerUp GPU Database

i now kinda pity i used the opportunity to grab this mainboard. Year or two ago it was Ati 690G aka Radeon X1250 - it could be even more amuzing :slight_smile: But i could not resist upgrading to native 6x SATA and native USB3 :slight_smile:

Can we perhaps just do somethign ultra-simple and then step procedure TGLRenderer.RenderShape(const Shape: TX3DRendererShape); line by line at my and your hardware, comparing local variables and taken if-branches ?

Every scene has separate, independent RenderOptions.

To adjust them all, assign callback to TCastleRenderOptions.OnCreate (class variable) to adjust it to have PhongShading := false. (Note that I just fixed related bug to it yesterday, Be more robust in case TCastleRenderOptions.OnCreate sets something · castle-engine/[email protected] · GitHub , so be sure you really use latest master when doing it.)

Of course, in this case it should not be needed.

Added to my TODO list. Admittedly it has low priority – for most normal engine usage, you have a project with CastleEngineManifest.xml ready.

That’s the culprit, and the reason why I asked for this report :slight_smile:

This enables the old-style rendering.

I’ll work on fixing that. Hm, but it’s not the first time this old rendering algorithm fails, because it didn’t get enough testing. I may also consider just removing this deprecated way of rendering.

In the meantime, please check whether changing FBuggyPureShaderPipeline := ... assignment you can find in castleglversion.pas into trivial FBuggyPureShaderPipeline := false fixes a problem for you. I suspect it may, and it would be the best solution.

it would take a slow clean-and-rebuild or IDE would throw an ICE for me again

i wish i could just GLVersion.BuggyPureShaderPipeline := False; instead.

tweaking those vars back and forth in runtime could be dangerous, but perhaps one-way (into more conservative of two options) would be safe?

Okay, it does NOT change bad rendering.

I made sure i actually do change it by

procedure TfmSea.FormResize(Sender: TObject);
  if nil = GLVersion then exit;

  Caption := Caption + '  GL ' + IntTOStr(Ord(

  OnResize := nil;

EnableFixedFunction is calculated looking at GLVersion.BuggyPureShaderPipeline. Which is why I asked to modify the castleglversion.pas, not try to tweak it later. Please test what happens if you modify the castleglversion.pas to have BuggyPureShaderPipeline always false.

In the meantime, I made a quick fix and committed to master. Please update to latest CGE master, and retest (and now make sure you leave the GLVersion.BuggyPureShaderPipeline as was autodetected in your case, i.e. true). It essentially forces PhongShading to be always false in case GLVersion.BuggyPureShaderPipeline.

We really should do better, treat above as just a quick solution.

  • We should enable Phong shading on this GPU.

  • We should actually remove the GLVersion.BuggyPureShaderPipeline concept. We should localize and fix cases why it fails (instead of “giving up on shader rendering”) in this case (it applies now to old drivers on Intel and ATI GPUs).

  • Ideally, both BuggyPureShaderPipeline and EnableFixedFunction should just cease to exist in the future. For some time, I guess I’ll display a big fat warning to people affected. We should “solve” the issue on their GPUs but keeping the shader rendering going, not giving up on it (i.e. we should not just revert to old way of rendering, which is in practice seldom tested so may cause bugs).

I will want to get my hands on affected ATI GPU for this.

i did, the render was still faulty, like i said above.

Maybe the fix (one of fixes) it the opposite direction?

If CGEngine - for whatever reason, right or wrong - settled on fixed function - then should it perhaps disable Phong? Is Phong given on any FFP ?


    FMaxClipPlanes := glGetInteger(GL_MAX_CLIP_PLANES)
    FMaxClipPlanes := glGetInteger(GL_MAX_CLIP_DISTANCES);

Both return 8

  FMaxViewportDimensions := GetVector2Integer(GL_MAX_VIEWPORT_DIMS);

gives 8192x8192

Thanks. I guess the BuggyPureShaderPipeline is (unfortunately) right in this case. I still would like to solve it better – maybe we can make exception for this GPU, but not such “drastic” exception where we just disable using shader pipeline. Perhaps some much-more-local exception for this GPU would make the shaders work OK there. As I said, I’ll try to get my hands on affected ATI GPU to experiment and make it better,

This is more or less what my last commit to master does. The BuggyPureShaderPipeline disables the Phong shading. (The EnableFixedFunction by itself does not – as fixed-function and shader pipeline may cooperate in many cases.)

Please test whether the latest master fixes the problem for you.