MichaelMitchell
MichaelMitchell

Reputation: 1167

opengl - unique color for each triangle

I am trying to shade my model such that each triangle is a solid, unique color based on its position in the buffer. I would like to know if this is a proper method of doing so.

You can skim to the last paragraph if you need no information about OpenGL

This is my Fragment Shader that will color based on the triangles' index in the buffer.

#version 420 core
out vec3 color
void main(){
    float r, g, b;
    r = (gl_PrimitiveID % 255) / 255.0f;
    g = ((gl_PrimitiveID / 255) % 255) / 255.0f;
    b = ((gl_PrimitiveID / (255 * 255)) % 255) / 255.0f;
    color = vec3(r, g, b);
}

It uses gl_PrimitiveID which essentially gives the location in the buffer of the triangle it is shading. So if I do a command to draw a buffer and say there are triangles in the buffer, gl_PrimitiveID will say that the first one is 0, then second triangle is 1, and the nth triangle is n-1.

OpenGL has its RGB values such that they are floats between 0.0f and 1.0f (I do not know if 1.0f is inclusive and is part of my problem).

If 1.0f end is inclusive I assume the method I have displayed above will work accurately, but if it is exclusive I think that I may have to divide by 256.0f instead of 255.0f. Which one is proper?

Example of replacement:

r = (gl_PrimitiveID % 255) / 256.0f; // notice 256.0f instead of 255.0f

Upvotes: 0

Views: 2286

Answers (2)

derhass
derhass

Reputation: 45362

I'd suggest an alternative wich might be much simpler. You wrote:

OpenGL has its RGB values such that they are floats between 0.0f and 1.0f (I do not know if 1.0f is inclusive and is part of my problem).

That is not true. OpenGL supports various different formats, floating-point, normalized integers and unnormalized integers. For your use case, I'd just suggest to use the format GL_R32UI, so that you can directly assign gl_PrimitiveID to the shader's output variable.

Upvotes: 1

MichaelMitchell
MichaelMitchell

Reputation: 1167

I decided to compare my usage of base 256 to a case with base 10:

[n / (10^digit_place)] % 10

This formula will give the number 0 through nine at the location of digit_place (whole numbers only).

For example, if you want to get the right most digit (one's place) of n = 1729 you do this:

steps:

  1. [1729 / (10^0)] % 10
  2. [1729 / (1)] % 10
  3. 1729 % 10
  4. ans = 9

Making this formula more abstract:

radix is a fancy term for the base number. Example: in normal numbers (0 - 9; base 10), the radix is 10

[n / (radix ^ place)] % radix

The Application To My Problem:

After doing some additional research, the rgb values in OpenGL are from 0.0f to 1.0f inclusive. This means that an rgb of (1.0f, 1.0f, 1.0f) is white, while an rgb of (0.0f, 0.0f, 0.0f) is black.

In byte form (0 - 255; base/radix 256), rgb values for white and black are as follows (in order), (255, 255, 255) and (0, 0, 0). Converting these values to a number between 0.0f and 1.0f is (again in order) (255/255.0f, 255/255.0f, 255/255.0f), (0/255.0f, 0/255.0f, 0/255.0f).

Comparing to my initial shader:

r = (gl_PrimitiveID % 255) / 255.0f;

The r in this example can only be between (inclusive) 0/255.0f and 254/255.0f. What we want is between (inclusive) 0/255.0f and 255/255.0f as shown above.

If we look at my calculation for r and compare it to the formula we see why we get a range of numbers that we do not want. The problem stems from this part: (gl_PrimitiveID % 255). Because of the way the modulo works, a modulo of n (n > 1) can only give whole number between 0 and n-1. In this case or n is 255 which gives us the problem range of 0 to 254. To solve this issue we simply replace 255 with 256 (which is the radix/base we are working with) and that makes this calculation work.

The Fixed Shader:

#version 420 core
out vec3 color
void main(){
    float r, g, b;
    // notice the 256's instead of 255
    r = (gl_PrimitiveID % 256) / 255.0f;
    g = ((gl_PrimitiveID / 256) % 256) / 255.0f;
    b = ((gl_PrimitiveID / (256 * 256)) % 256) / 255.0f;
    color = vec3(r, g, b);
}

Upvotes: 0

Related Questions