Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rlgl] glVertexAttribPointer() error client-side with WebGL 2.0 (OpenGL ES 3.0) #4330

Open
tomlikesnakes opened this issue Sep 19, 2024 · 4 comments
Labels
platform: Web Web platform

Comments

@tomlikesnakes
Copy link

tomlikesnakes commented Sep 19, 2024

Hello,

There is an error when targetting webgl2 and using whatever Draw function you want (like DrawRectangle/cube/text etc)

index.js:7373 Uncaught TypeError: Cannot set properties of undefined (setting 'clientside')
    at _glVertexAttribPointer

I did a very minimal example here :

#include <raylib.h>
#include <emscripten.h>

const int screenWidth = 800;
const int screenHeight = 450;

void draw(void) {
    BeginDrawing();

    ClearBackground(RAYWHITE);

    DrawRectangle(200, 150, 400, 200, RED);

    DrawText("Hello, WebAssembly with Raylib!", 210, 200, 20, BLACK);

    EndDrawing();
}

int main() {
    InitWindow(screenWidth, screenHeight, "raylib with Emscripten - Simple Draw");

    SetTargetFPS(60);

    emscripten_set_main_loop(draw, 0, 1);

    CloseWindow();

    return 0;
}


compilation flag :

emcc -o index.html testthatfail.c -I/home/tom/raylib-wasm/src     
-L/home/tom/raylib-wasm/src -lraylib -DPLATFORM_WEB     -s USE_GLFW=3 -s FULL_ES3=1 -s MIN_WEBGL_
VERSION=2 -s MAX_WEBGL_VERSION=2 -s ASYNCIFY

I tried with only full_es2, with different things for memory and so.

For this kind of things it is not really problematic but for my other project I need to create vertex buffer and go with opengl (not rlgl) and use shaders for a cube, and i need the webgl2/opengl300es for my futures things on the project

@tomlikesnakes tomlikesnakes changed the title glVertexAttribPointer error client-side with opengl es300 on weblgl2 glVertexAttribPointer error client-side with opengl es300 on webgl2 Sep 19, 2024
@tomlikesnakes
Copy link
Author

Okay it's due to the flag FULL_ES from emscripten

@tomlikesnakes
Copy link
Author

We got these warning when removed the -s FULL_ES2=1 (or FULL_ES3=1) that transform themselves to errors

128WebGL: INVALID_VALUE: vertexAttribPointer: index out of range
128WebGL: INVALID_VALUE: enableVertexAttribArray: index out of range
index.js:5086 WebGL: too many errors, no more errors will be reported to the console for this context.

@tomlikesnakes
Copy link
Author

this works :

#include <raylib.h>
#include <emscripten.h>
#include <GLES3/gl3.h> 

const int screen_width = 800;
const int screen_height = 450;

GLuint shader_program;
GLint pos_attrib;
GLuint vbo, vao;

// Vertex data for a simple triangle
float vertices[] = {
    -0.5f, -0.5f, 0.0f, 
     0.5f, -0.5f, 0.0f, 
     0.0f,  0.5f, 0.0f
};

void draw(void) {
    BeginDrawing();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(shader_program);
    TraceLog(LOG_INFO, "Using shader program %d", shader_program);

    glBindVertexArray(vao);
    TraceLog(LOG_INFO, "Bound VAO %d", vao);

    glDrawArrays(GL_TRIANGLES, 0, 3);
    TraceLog(LOG_INFO, "DrawArrays executed");

    EndDrawing();
}

void setup_shaders() {
    // Vertex shader that uses the 'position' attribute
    const char* vertex_shader_source = "#version 300 es\n"
        "precision mediump float;\n"
        "layout(location = 0) in vec3 position;\n"
        "void main() {\n"
        "    // Use each component of position and assign it to gl_Position\n"
        "    gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
        "}\n";

    // Fragment shader that uses frag_color
    const char* fragment_shader_source = "#version 300 es\n"
        "precision mediump float;\n"
        "out vec4 frag_color;\n"
        "void main() {\n"
        "    // Output a constant red color\n"
        "    frag_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
        "}\n";

    GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);

    GLint vertex_compile_status;
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
    if (!vertex_compile_status) {
        char info_log[512];
        glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
        TraceLog(LOG_ERROR, "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s", info_log);
    }

    GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);

    GLint fragment_compile_status;
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
    if (!fragment_compile_status) {
        char info_log[512];
        glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
        TraceLog(LOG_ERROR, "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s", info_log);
    }

    // Create shader program and link shaders
    shader_program = glCreateProgram();
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    glLinkProgram(shader_program);

    // Validate shader program
    GLint is_linked;
    glGetProgramiv(shader_program, GL_LINK_STATUS, &is_linked);
    if (!is_linked) {
        char info_log[512];
        glGetProgramInfoLog(shader_program, 512, NULL, info_log);
        TraceLog(LOG_ERROR, "ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s", info_log);
    }

    // Use the shader program
    glUseProgram(shader_program);

    // Get attribute location
    pos_attrib = glGetAttribLocation(shader_program, "position");
    TraceLog(LOG_INFO, "Attribute 'position' location (queried in setup): %d", pos_attrib);

    // Create VAO and VBO for triangle
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Enable the attribute array and set up pointer
    if (pos_attrib >= 0) {
        glEnableVertexAttribArray(pos_attrib);
        glVertexAttribPointer(pos_attrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
        TraceLog(LOG_INFO, "VertexAttribPointer set for location %d", pos_attrib);
    } else {
        TraceLog(LOG_ERROR, "Invalid attribute location for 'position'");
    }

    // Unbind VAO (optional)
    glBindVertexArray(0);
}

int main() {
    InitWindow(screen_width, screen_height, "raylib with Emscripten - Proper Shaders");

    // Setup the shaders and VBO/VAO
    setup_shaders();

    SetTargetFPS(60);

    // Emscripten loop
    emscripten_set_main_loop(draw, 0, 1);

    CloseWindow();

    return 0;
}

this not (cause of previous warning from enableVertexAtribArray and so) :

#include <raylib.h>
#include <emscripten.h>
#include <rlgl.h>
#include <GLES3/gl3.h>  

const int screen_width = 800;
const int screen_height = 450;

Shader custom_shader;
unsigned int vbo, vao;
int position_loc;

void draw(void) {
    BeginDrawing();
    
    ClearBackground(RAYWHITE);

    rlEnableShader(custom_shader.id);

    // Bind the VAO (which contains the VBO with our vertex data)
    glBindVertexArray(vao);  // Use OpenGL to bind the VAO

    // Draw the triangle using the bound VAO
    glDrawArrays(GL_TRIANGLES, 0, 3);  // Draw 3 vertices (1 triangle)

    // Unbind the VAO after drawing
    glBindVertexArray(0);  // Unbind VAO to avoid issues later

    // End custom shader mode
    rlDisableShader();

    // Render some debug text
    DrawText("Triangle rendered using OpenGL and rlgl!", 210, 400, 20, BLACK);

    EndDrawing();
}

void setup_gl_buffers() {
    // Define the vertex data for a simple triangle (position only)
    float vertices[] = {
        // Positions
        -0.5f, -0.5f, 0.0f,   // Bottom-left
         0.5f, -0.5f, 0.0f,   // Bottom-right
         0.0f,  0.5f, 0.0f    // Top-center
    };

    // Generate and bind a VAO
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // Generate and bind a VBO
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // Upload the vertex data to the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Use the location retrieved from `rlgl` instead of hardcoding 0
    glEnableVertexAttribArray(position_loc);  // Use attribute location from `rlgl`
    glVertexAttribPointer(position_loc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    // Unbind the VBO and VAO to avoid accidental modification
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

void setup_rlgl_shader() {
    // Vertex shader with a 'position' attribute
    const char* vertex_shader_code = "#version 300 es\n"
        "precision mediump float;\n"
        "layout(location = 0) in vec3 position;\n"  // 'position' attribute
        "void main() {\n"
        "    gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"  // Use each component of position
        "}\n";

    // Fragment shader outputting a red color
    const char* fragment_shader_code = "#version 300 es\n"
        "precision mediump float;\n"
        "out vec4 frag_color;\n"
        "void main() {\n"
        "    frag_color = vec4(1.0, 0.0, 0.0, 1.0);\n"  // Output red color
        "}\n";

    // Load custom shader from code
    custom_shader = LoadShaderFromMemory(vertex_shader_code, fragment_shader_code);

    // Check for any shader compilation/linking errors
    if (custom_shader.id == 0) {
        TraceLog(LOG_ERROR, "Shader program failed to load.");
        return;
    }

    // Get the location of the 'position' attribute from the custom shader
    position_loc = GetShaderLocationAttrib(custom_shader, "position");
    TraceLog(LOG_INFO, "Shader position attribute location: %d", position_loc);

    if (position_loc == -1) {
        TraceLog(LOG_ERROR, "Failed to get position attribute location");
        return;
    }
}

int main() {
    InitWindow(screen_width, screen_height, "raylib with Emscripten - OpenGL + rlgl");

    // Setup the OpenGL buffers (VBO/VAO)
    setup_gl_buffers();

    // Setup the custom shader
    setup_rlgl_shader();

    SetTargetFPS(60);

    // Emscripten loop
    emscripten_set_main_loop(draw, 0, 1);

    // Cleanup
    UnloadShader(custom_shader);  // Unload the shader when done
    glDeleteBuffers(1, &vbo);     // Delete the VBO
    glDeleteVertexArrays(1, &vao); // Delete the VAO
    CloseWindow();                // Close the window and OpenGL context

    return 0;
}

-> the way rlgl manage shaders is not consistent that's why for the second example I also tried to use opengl with rlgl (also tried only rlgl but got same warnings)
-> From what I see for opengl 300es webgl2 you always need shaders and you always need to really have all in/out var clearly pass and defined (like each components of pos) and manually create vao/vbo with vertex data

for now I'm going to use pure opengl cause I really need the opengl 300es, If someone can have a look and correct what I found or anything I'm here

@raysan5 raysan5 changed the title glVertexAttribPointer error client-side with opengl es300 on webgl2 [rlgl] glVertexAttribPointer() error client-side with WebGL 2.0 (OpenGL ES 3.0) Sep 20, 2024
@raysan5 raysan5 added the platform: Web Web platform label Sep 20, 2024
@raysan5
Copy link
Owner

raysan5 commented Sep 20, 2024

@tomlikesnakes Thanks for reporting! Actually, OpenGL ES 3.0 has been added recently as a backend GL option to raylib and it has not been widely tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: Web Web platform
Projects
None yet
Development

No branches or pull requests

2 participants