Jump to content
  • Advertisement
alex1997

OpenGL How to render multiple objects with different shaders

Recommended Posts

I'm looking to render multiple objects (rectangles) with different shaders. So far I've managed to render one rectangle made out of 2 triangles and apply shader to it, but when it comes to render another I get stucked. Searched for documentations or stuffs that could help me, but everything shows how to render only 1 object. Any tips or help is highly appreciated, thanks!

Here's my code for rendering one object with shader!

 

	#define GLEW_STATIC
	
	#include <stdio.h>
	#include <GL/glew.h>
	#include <GLFW/glfw3.h>
	
	#include "window.h"
	
	#define GLSL(src) "#version 330 core\n" #src
	// #define ASSERT(expression, msg) if(expression) {fprintf(stderr, "Error on line %d: %s\n", __LINE__, msg);return -1;}
	
	int main() {
	    // Init GLFW
	    if (glfwInit() != GL_TRUE) {
	        std::cerr << "Failed to initialize GLFW\n" << std::endl;
	        exit(EXIT_FAILURE);
	    }
	    // Create a rendering window with OpenGL 3.2 context
	    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
	    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
	
	    // assing window pointer
	    GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
	    glfwMakeContextCurrent(window);
	    // Init GLEW
	    glewExperimental = GL_TRUE;
	    if (glewInit() != GLEW_OK) {
	        std::cerr << "Failed to initialize GLEW\n" << std::endl;
	        exit(EXIT_FAILURE);
	    }
	    // ----------------------------- RESOURCES ----------------------------- //
	
	    // create gl data
	    const GLfloat positions[8] = {
	        -0.5f, -0.5f,
	         0.5f, -0.5f,
	         0.5f,  0.5f,
	        -0.5f, 0.5f,
	    };
	
	    const GLuint elements[6] = {
	        0, 1, 2,
	        2, 3, 0
	    };
	
	    // Create Vertex Array Object
	    GLuint vao;
	    glGenVertexArrays(1, &vao);
	    glBindVertexArray(vao);
	
	    // Create a Vertex Buffer Object and copy the vertex data to it
	    GLuint vbo;
	    glGenBuffers(1, &vbo);
	    glBindBuffer(GL_ARRAY_BUFFER, vbo);
	    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
	    // Specify the layout of the vertex data
	    glEnableVertexAttribArray(0); // layout(location = 0)
	    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
	    
	    // Create a Elements Buffer Object and copy the elements data to it
	    GLuint ebo;
	    glGenBuffers(1, &ebo);
	    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements),  elements, GL_STATIC_DRAW);
	    
	
	    // Create and compile the vertex shader
	    const GLchar *vertexSource = GLSL(
	        layout(location = 0) in vec2 position;
	        
	        void main() {
	            gl_Position = vec4(position, 0.0, 1.0);
	        }
	    );
	
	    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	    glShaderSource(vertexShader, 1, &vertexSource, NULL);
	    glCompileShader(vertexShader);
	
	    // Create and compile the fragment shader
	    const char* fragmentSource = GLSL(
	        out vec4 gl_FragColor;
	        uniform vec2 u_resolution;
	        
	        void main() {
	            vec2 pos = gl_FragCoord.xy / u_resolution;
	          
	            gl_FragColor = vec4(1.0);
	        }
	    );
	
	    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
	    glCompileShader(fragmentShader);
	
	    // Link the vertex and fragment shader into a shader program
	    GLuint shaderProgram = glCreateProgram();
	    glAttachShader(shaderProgram, vertexShader);
	    glAttachShader(shaderProgram, fragmentShader);
	    glLinkProgram(shaderProgram);
	    glUseProgram(shaderProgram);
	
	    // get uniform's id by name and set value
	    GLint uRes = glGetUniformLocation(shaderProgram, "u_Resolution");
	    glUniform2f(uRes, 800.0f, 600.0f);
	        
	    // ---------------------------- RENDERING ------------------------------ //
	
	    while(!glfwWindowShouldClose(window)) {
	        // Clear the screen to black
	        glClear(GL_COLOR_BUFFER_BIT);
	        glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
	        
	        // Draw a rectangle made of 2 triangles -> 6 vertices
	        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
	
	        // Swap buffers and poll window events
	        glfwSwapBuffers(window);
	        glfwPollEvents();
	    }
	
	    // ---------------------------- CLEARING ------------------------------ //
	
	    // Delete allocated resources
	    glDeleteProgram(shaderProgram);
	    glDeleteShader(fragmentShader);
	    glDeleteShader(vertexShader);
	    glDeleteBuffers(1, &vbo);
	    glDeleteVertexArrays(1, &vao);
	
	    return 0;
	}

 

Edited by alex1997

Share this post


Link to post
Share on other sites
Advertisement

Without seeing how you are currently doing it, I can only really give a generic example, but you basically just want to create all your shaders, select the shader you wish to use - render all items that use this shader, switch to the next shader, render all items that use that shader, and so on

Switching shaders can be expensive, so thats why you will want to do all items for each shader before moving to the next, rather then switching shaders depending on what your rendering at the time.

If you can show a small bit of code of how you are currently doing this, im sure you will get more specific anwers

Share this post


Link to post
Share on other sites
26 minutes ago, McGrane said:

Without seeing how you are currently doing it, I can only really give a generic example, but you basically just want to create all your shaders, select the shader you wish to use - render all items that use this shader, switch to the next shader, render all items that use that shader, and so on

Switching shaders can be expensive, so thats why you will want to do all items for each shader before moving to the next, rather then switching shaders depending on what your rendering at the time.

If you can show a small bit of code of how you are currently doing this, im sure you will get more specific anwers

Thanks! I've pasted my code above And yes, beofre rendering wanna attach the shader and when the objects are ready draw them.

Share this post


Link to post
Share on other sites

Yeah, so in the above, you are creating a shader- and then telling opengl to use this shader:

glUseProgram(shaderProgram);

If you wish to use another shader, you do the same as you have done above in creating, compiling and linking another shader. You may want to extend your above to read shaders from text files instead of implementing them in code, and maybe making a shader class to encapsulate all these methods to just make it easier for maintainability. However to just get this working as is, say you have two shaders, and have compiled the into shaderProgram1 and shaderProgram2 then too use them you could just do something like:

3 hours ago, alex1997 said:

glUseProgram(shaderProgram1);

// Draw a rectangle made of 2 triangles -> 6 vertices glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);

glUseProgram(shaderProgram2);

// Draw a rectangle made of 2 triangles -> 6 vertices glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);

If you haven't already, check out https://learnopengl.com/ there are sections on shaders, and code examples for how he has set up his shader classes - along with alot of other great information

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!