Results 1 to 5 of 5

Thread: Need explanation for glDrawArraysInstanced()

  1. #1
    Newbie Newbie
    Join Date
    Feb 2018
    Posts
    12

    Question Need explanation for glDrawArraysInstanced()

    Hello guys,
    While experimenting with OpenGL It seems I do not understand something with GlDrawArraysInstanced()

    I want to achieve: 1INT of an Array = 1 COLOR = 1 INSTANCE = 2TRIANLES = 1 SQUARE

    I have a map that fits my screen with integers, each representing a color (4 differents available):

    Code :
     
            int map_size = tile_x*tile_y;
    	int *mapmat = new int [map_size];
     
    	for (int i = 0; i < map_size; i++) {
    		mapmat[i] = (i % 4);
    	}
    	mapmat[0] = 3; //3 is grey
    	mapmat[1] = 2; //2 is blue
    	mapmat[2] = 1; //1 is green
    	mapmat[3] = 0; //0 is red
    	mapmat[4] = 3;
    	mapmat[5] = 1;

    I feed it into a buffer and bind it to a VAO:

    Code :
            GLuint vbo;
            glGenBuffers(1, &vbo);
            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBufferData(GL_ARRAY_BUFFER, sizeof(mapmat), mapmat, GL_STATIC_DRAW);
     
    	GLuint shaderProgram = graphic_engine::compile_program("shader/simple.vs","shader/simple.fs");
    	glUseProgram(shaderProgram);
     
    	GLuint matAttrib = glGetAttribLocation(shaderProgram, "mat");
    	glEnableVertexAttribArray(matAttrib);
    	glVertexAttribIPointer(matAttrib, 1, GL_INT, 0, 0);
    	glVertexAttribDivisor(matAttrib,1);

    here are about my vertex and fragment shaders:

    Code :
    #version 150 core //VERTEX SHADER
    #extension GL_ARB_explicit_attrib_location : require
     
    layout (location = 0) in int mat;
    layout (location = 1) uniform vec4 screen; //rx,ry,tile_x,tile_y //some screen settings used only set once ...
     
    out VS_OUT
    {
    	vec4 color;
    }vs_out;
     
    	// triangles layout
    	// 2------1
    	// |        /|
    	// |      /  |
    	// |    /    |
    	// |  /      |
    	// |/        |
    	// 0------3
    	const int indexes[6]={0,1,2,0,3,1};
     
    void main() {
     
     
    	float rx = screen[0];
    	float ry = screen[1];
     
    	int tx = int(screen[2]);
    	int ty = int(screen[3]);
     
    	float ox = -1.0 + rx*(gl_InstanceID % tx);
    	float oy = 1.0 - ry*(gl_InstanceID / tx) ;
     
    	vec4 vertices[4]= vec4[4](
    	vec4(ox,oy-ry,0.5,1.0),
    	vec4(ox+rx,oy,0.5,1.0),
    	vec4(ox,oy,0.5,1.0),
    	vec4(ox+rx,oy-ry,0.5,1.0)
    	);
     
    	const vec4 colors[4]= vec4[4](
    	vec4(1.0,0.0,0.0,1.0),
    	vec4(0.0,1.0,0.0,1.0),
    	vec4(0.0,0.0,1.0,1.0),
    	vec4(0.5,0.5,0.5,1.0)
    	);
     
    	gl_Position = vertices[indexes[gl_VertexID]]; //array of the 6 needed vertices
    	vs_out.color = colors[mat]; //the color corresponding to the map
    }


    Code :
    #version 150 core //FRAGMENT SHADER
     
    in VS_OUT
    {
    	vec4 color;
    }vs_out;
     
    uniform vec4 screen; //rx,ry,tile_x,tile_y
     
    out vec4 colorout;
     
    void main() {
     
    	colorout =vs_out.color;
    }


    I call this each frame:

    Code :
    glDrawArraysInstanced(GL_TRIANGLES, 0,6, tile_x*tile_y);

    and here is my output:
    Attachment 152


    What do I miss Here ?
    I don't really understand when the Fragment shader gets data, it's supposed to be per vertex, and I already achieved to put one color per vertex, but what if I want the same color for the 6 vertices of a square ?
    Attached Images Attached Images

  2. #2
    Senior Member Regular Contributor
    Join Date
    May 2016
    Posts
    477
    Quote Originally Posted by puregainz View Post
    I don't really understand when the Fragment shader gets data, it's supposed to be per vertex, and I already achieved to put one color per vertex, but what if I want the same color for the 6 vertices of a square ?
    once you call "glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100)", opengl has to execute a "glDrawArrays(GL_TRIANGLES, 0, 6)" command 100x times, you can use the built-in variable "gl_InstanceID" in the vertexshader which will be 0..99 in this case

    once a "glDrawArrays(GL_TRIANGLES, 0, 6)" command is called, you invoke the vertexshader 6 times
    GL_TRIANGLES means that each 3 vertices, the vertices for a triangle primitive will be send to the rasterizer, it determines what pixels are covered by the triangle, and on each covered pixel the fragmentshader executes

    for example, if you have 1 triangle that covers half of a 1024 x 1024 window, the vertexshader will only be invoked 3 times, but the fragmentshader will be invoked 1024 x 1024 / 2 = 524.288 times

    you can pass data from the vertexshader to the fragmentshader, like a "vec4 color" value, that value gets interpolated within the triangle (if you dont set another interpolation qualifier explicitly, like "flat"). "integer type" variables (like int or uint) cant be interpolated, so you have to either pass them with the "flat" qualifer (that means only the last passed value will be used by ALL pixels of that triangle) or use another way to access that information in the fragmentshader

    by the way: did you check for GL errors and shader compilation / linking errors ?
    https://www.khronos.org/opengl/wiki/OpenGL_Error
    https://www.khronos.org/opengl/wiki/...lation#Example

  3. #3
    Newbie Newbie
    Join Date
    Feb 2018
    Posts
    12
    Thanks for the answer,

    yeah I am checking both compile and linking errors and none occurs
    I also use glIntercept, a windows tool to get more info about OpenGL errors and the logs show nothing.

    I am aware of Vertex Provoking and have already tried the "flat" qualifiers, it doesn't change anything ,
    does it requires an extension on GLSL core 150 to work properly ?

    The most frustrating is passing gl_InstanceID to the fragment shader as an flat int in attribute and doing so works:

    Code :
    colorout = colors[gl_InstanceID % 4]
    (it produces a nice 4 colored checker board)

    but passing the int "mat" instead produces the same strange output.
    That means, "mat" isn't sent from the vertex to the fragment shader properly for some reason

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,100
    Quote Originally Posted by puregainz View Post
    does it requires an extension on GLSL core 150 to work properly ?
    gl_InstanceID exists in GLSL 1.50 core profile.

    One obvious issue with your code is that the buffer size is wrong:
    Quote Originally Posted by puregainz View Post
    Code :
    	int *mapmat = new int [map_size];
    ...
            glBufferData(GL_ARRAY_BUFFER, sizeof(mapmat), mapmat, GL_STATIC_DRAW);
    sizeof(mapmat) will be the size of a pointer, not the size of the array it points to. Use map_size*sizeof(int), or use a std::vector rather than a bare array.

  5. #5
    Newbie Newbie
    Join Date
    Feb 2018
    Posts
    12
    The obvious one's are always the most frustrating, you are my savior.

    I experimented a bit more with this size,stride, offset mess and understood the whole thing better, thank you !

Similar Threads

  1. Performance issue with glDrawArraysInstanced
    By lmoretto88 in forum OpenGL: Basic Coding
    Replies: 0
    Last Post: 04-09-2014, 06:37 AM
  2. Explanation please
    By _Syndic in forum OpenGL: Basic Coding
    Replies: 0
    Last Post: 05-02-2013, 09:47 AM
  3. glDrawArraysInstanced max number of instances?
    By mokafolio in forum OpenGL: Advanced Coding
    Replies: 3
    Last Post: 03-01-2013, 06:43 PM
  4. Picking when using glDrawArraysInstanced
    By walkins in forum OpenGL: Basic Coding
    Replies: 6
    Last Post: 11-04-2011, 05:04 AM
  5. just an explanation
    By grimoire in forum OpenGL: Basic Coding
    Replies: 5
    Last Post: 04-18-2004, 07:52 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean