简体   繁体   中英

State dependant rendering in fragment shader

I am currently working on my bachelor thesis which is about creating a 3D-Visualisation of a warehouse using the GWT plugin gwt-g3d.

I've come as far as being able to display the structual layout quite efficiently. Rendering 2 million+ vertextes at a decent framerate since I keep all the rendering within the shaders and minimize my gl.draw() calls. However, I think I've come to a dead end using this technique since it is very static. What I need is a way to make my application more dynamic. As I am used to object orientated programming in Java the shader language is quite hard to get my head around. Here's what I'm talking about...

I'm trying to render multiple areas (the number of these areas is UNKNOWN at initialisation) of my visualisation in a different manner (a different color to start with). So ive tried something like this within the fragment shader:

...
uniform vec3 alteredCoords[]; //a coordArray of positions that i want to render alternatively
...

// color each of these coords in grey
for (int i = 0; i < alteredCoords.length(); i++) {
  if ( position.x == alteredCoords[i].x && position.y == alteredCoords[i].y && position.z == alteredCoords[i].z) {
    gl_FragColor = vec4(100.0/255.0, 100.0/255.0, 100.0/255.0, 1.0);
    return;
  }
}

I know that this won't work as it is, because the array needs a constant size and there are casting issues — try to ignore that for now since this won't work anyways because the shader language doesn't support dynamically sized arrays.

What I need is some sort of workaround for this issue. Any ideas?

Here's a screenshot of what my layout looks like at the moment:

Notice that I've implemented my idea for a single area (grey square) already — all I need is some way to dynamically render multiple areas that way.

Here is the typical workaround for getting dynamically sized arrays in a fragment shader:

Textures!

To be more specific, you can pass in an n x m pixel texture (with nearest neighbor resampling), and pass in the values n and m as uniforms. The texture sampler uses normalized uv coordinates, so you can just construct a mapping function like so:

uniform sampler2D sampler;
uniform float n;
uniform float m;

vec4 get_texel(float idx) {
    vec2 idx2d = vec2(
        (mod(idx, n) + 0.5) / n,
        (floor(idx / n) + 0.5) / m);
    return texture2D(sampler, idx2d);
}

Now you have a variable sized array of vec4 s

To expand on this further, assuming your shelves are arranged in a regular grid, you could very easily create a mapping function which takes the world coordinate of the current fragment and maps it to a particular pixel in the texture you've passed in, then use the value of the texture to choose how to render said fragment.

As the information about what you want to draw differently is associated with the vertices, you probably would do best to transfer the information to the pipeline along with those vertices, using vertex attributes . I'm no expert on this, but I assume that anything else will likely be more expensive than this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM