Skip to content

[models] Instanced Drawing with Custom Shader Corrupts Drawing with Default Shader #2511

Closed
@TheTophatDemon

Description

@TheTophatDemon
  • I tested it on latest raylib version from master branch
  • I checked there is no similar issue already reported
    (#2211 is related but isn't the same sort of issue).
  • My code has no errors or misuse of raylib

Issue description

In my original project, I was trying to draw instanced copies of a particular mesh, and then use that same mesh to draw a non-instanced version of it with the default material. However, something about the DrawMeshInstanced(...) call seemed to corrupt the state of the renderer and made the non-instanced version not draw correctly.

This only occurs when the vertex shader of the instanced material does not declare the attributes for vertex normal and color, which can be demonstrated by replacing the example's shader with "based_lighting_instanced.vs" from the raylib examples.

Although this can be seen as a misconfiguration on the user's end, this error does not occur when instancing is not involved. Even so, an error in the instanced vertex shader should not affect rendering using the default shader as well.

Environment

Linux, Pop! OS (Ubuntu & Gnome desktop), OpenGL 4.6.0 NVIDIA 510.73.05, NVIDIA GeForce GTX 1650, NVIDIA proprietary driver version 510.73.05

Issue Screenshot

Result of the code example below:
image
Result of the code example, with the DrawMeshInstanced(...) line removed.
image
Expected result (Achieved by replacing "base_instanced_stripped.vs" with "base_lighting_instanced.vs")
image

Code Example

#include "raylib.h"
#include "raymath.h"

#include <stdlib.h>
#include <math.h>

#define MAX_INSTANCES  10

int main(void)
{
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mesh instancing");
    SetTargetFPS(60);

    Camera camera = { 0 };
    camera.position = (Vector3){ -25.0f, 25.0f, -25.0f };
    camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
    camera.fovy = 45.0f;
    camera.projection = CAMERA_PERSPECTIVE;
    SetCameraMode(camera, CAMERA_ORBITAL);

    Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);

    Matrix *transforms = RL_MALLOC(MAX_INSTANCES*sizeof(Matrix));

    for (int i = 0; i < MAX_INSTANCES; i++) {
        transforms[i] = MatrixTranslate(0.0f, -10.0f, 0.0f);
    }

    //Load a shader that's missing attributes for vertex color and normals.
    Shader shader = LoadShader("resources/shaders/glsl330/base_instanced_stripped.vs",
                               "resources/shaders/glsl330/base.fs");

    shader.locs[SHADER_LOC_MATRIX_MVP] = GetShaderLocation(shader, "mvp");
    shader.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocationAttrib(shader, "instanceTransform");
    
    //Instanced material
    Material instancedMaterial = LoadMaterialDefault();
    instancedMaterial.shader = shader;
    instancedMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RED;
    
    //Non instanced material
    Material normalMaterial = LoadMaterialDefault();
    normalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = BLUE;

    while (!WindowShouldClose())
    {
        UpdateCamera(&camera);
        
        BeginDrawing();

            ClearBackground(RAYWHITE);

            BeginMode3D(camera);
            	//The cubes drawn before and after the instanced draw call are not rendered unless the instanced draw call is removed.
                DrawMesh(cube, normalMaterial, MatrixTranslate(-2.0f, 0.0f, 0.0f));
                
                DrawMeshInstanced(cube, instancedMaterial, transforms, MAX_INSTANCES);
                
                DrawMesh(cube, normalMaterial, MatrixTranslate(2.0f, 0.0f, 0.0f));
            EndMode3D();

        EndDrawing();
    }
	
    RL_FREE(transforms);

    CloseWindow(); 

    return 0;
}

Shader code for "base_instanced_stripped.vs":

#version 330

in vec3 vertexPosition;
in vec2 vertexTexCoord;

in mat4 instanceTransform;

uniform mat4 mvp;
uniform mat4 matNormal;

out vec3 fragPosition;
out vec2 fragTexCoord;

void main()
{
    mat4 mvpi = mvp*instanceTransform;

    fragPosition = vec3(mvpi*vec4(vertexPosition, 1.0));
    fragTexCoord = vertexTexCoord;

    gl_Position = mvpi*vec4(vertexPosition, 1.0);
}

Other shaders mentioned are from the raylib examples repository.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions