Ray Tracing a scene with triangle meshes with webg

2019-09-01 04:15发布

问题:

after my original post was flagged as "too broad" by other stack overflow users. I will rephrase my question in less lines. I have implemented a ray marcher in shadertoy, and i understood all the math about the ray-object intersection. And i want to make the next step to ray trace with meshes. I found out that doing so needs to be done with deferred rendering and framebuffers(2 pass rendering, one for the geometry and the other for the lighting calculations, the ray tracing) and the intersections will happen with ray-triangle intersection.

Of course i will post some code in the next weeks as i will start implementing this. and i will need some specific help but till then i would appreciate the help in order to now waste time searching the web. This is why i posted here..

original post as it was flagged "too broad"

this is my first ever post to stack overflow. My goal is to write a ray tracer with mesh objects.

So far the only thing i have accomplished is make a ray tracer with spheres and planes. This is done with forward rendering, and while creating all the geometry in the fragment shader(which is easy to produce the spheres and the plane).

After all the research that i have made i finally found the solution. This is accomplished with deferred shading technique where you create the geometry and pass it to the G-buffer as a texture and then with the second pass you start the calculations for the lighting and the ray tracing.

I am seeking guidance cause i have spent many days/months(3-4) in order to come to this conclusion since i was not familiar with neither shaders nor the graphics libraries. My questions are the following:

1) Is this approach the correct one? 2) And second can someone guide me to the triangle intersections? By the term triangle intersections i don't mean the math and the procedure of ray-triangle intersection; i know about that. What i don't know is after the first intersection, how to check for the next collision, how to test the next triangle. In what way do i need to pass the vertexes in the G-buffer in order to traverse through them and check for intersections(some sample glsl code would be nice to understand)?

here are the links that i have read in order to come to that conclution

  1. https://www.opengl.org/discussion_boards/showthread.php/200487-Ray-intersection-with-GLSL
  2. https://www.imgtec.com/blog/five-steps-to-adding-ray-tracing-to-an-opengl-es-based-deferred-lighting-system/
  3. https://learnopengl.com/Advanced-Lighting/Deferred-Shading
  4. GPU PRO 6 book, page 351-368

If i missed any link in the stack overflow community please post them here.

I would appreciate any answer relative to the answer. Thank you in advance.

回答1:

I'm also self thought, had a hard time starting. But it is very easy.
You need to pack your mesh data into an RGB(A) texture and then uppack it inside the fragment shader
some really good pfds on this technique, here is one example: http://www.cs.harvard.edu/~sjg/papers/gim.pdf

exampel of texture layout:
using RGB ( Alpha Channel can be used for meterial index )

             colums       colums      colums
        |      0      |     1     |      2
        |  R   G   B  | R   G   B |  R   G   B
        |-------------|-----------|-----------
    rows|  1   0   0  |           |

CPU side:
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB32F, dataLenght/channels, 1, 0, gl.RGB, gl.FLOAT, meshVerts);
texImage2D reference
GPU side:
texelFetch(uMeshData, ivec2(vertIndex, 0), 0);
texelFetch reference


Some Resources/LINKS:
Written in C++ but actually the conversation is not that far away to an #version 300 es glsl shader:
scratchapixel
OpenGL Development Cookbook has some expampels reading obj to image to fragment
the source on github
i personaly think this is the best pathtracer on the web:
with me little knowledge i can see that this guy read the Physically Based Rendering book to the very end
here is really good tutorial to understand the concept of computer graphics
UPDATE/EDIT: Peter Shirleys Raytracing in a Weekend is free for download


my own little attempt

(() => {
'use strict';
// vertex
const vs = `#version 300 es\nin vec2 p;out vec2 vuv;void main(){gl_Position = vec4(vuv = p, 0, 1);}`;

// fragment
const fs = `#version 300 es\n
precision highp float;
precision highp int;
precision highp sampler2D; 
in vec2 vuv;
uniform float time;
uniform vec2 Res, mouse;
uniform sampler2D uMeshData;
uniform int vertsCount;
layout(location = 0) out lowp vec4 fragColor;

struct Ray {
  vec3 orig, dir;
}R_;

mat4 rotate() {
float x = mouse.x, y=mouse.y+sin(time*2.),z=0.;
  float a = sin(x), b = cos(x), c = sin(y), d = cos(y), e = sin(z), f = cos(z), ac = a * c, bc = b * c;
  return mat4(d * f, d * e, -c, 0.0, ac * f - b * e, ac * e + b * f, a * d, 0.0, bc * f + a * e, bc * e - a * f, b * d, 0.0, 0.0, 0.0, 0.0, 1.0);
}

// https://github.com/Jojendersie/gpugi/blob/5d18526c864bbf09baca02bfab6bcec97b7e1210/gpugi/shader/intersectiontests.glsl#L63
bool isTriangle(Ray ray, in vec3 p0, in vec3 p1, in vec3 p2, out vec3 N) {
  vec3 e0 = p1 - p0, e1 = p0 - p2;
  N = cross(e1, e0);
  vec3 e2 = (1.0 / dot(N, ray.dir)) * (p0 - ray.orig);
  vec3 i = cross(ray.dir, e2);
  vec3 b = vec3(0.0, dot(i, e1), dot(i, e0));
  b.x = 1.0 - (b.z + b.y);
  return (dot(N, e2) > 1e-8) && all(greaterThanEqual(b, vec3(0.0)));
}

void Camera(out Ray ray, vec3 lookAt, vec3 up, float angle, float aspect) {
  vec3 g = normalize(lookAt - ray.orig);
  vec3 u = normalize(cross(g, up));
  vec3 v = normalize(cross(u, g));
  u = u * tan(radians(angle * .5));
  v = v * tan(radians(angle * .5)) / aspect;
  ray.dir = normalize(g + ray.dir.x * u + ray.dir.y * v);
}

void main() {
  vec3 SceneCol = vec3(0.5);
  
  vec3 hit = vec3(0.);
  vec4 a = vec4(0.0), b = vec4(0.0), c = vec4(0.0);
  
  R_ = Ray(vec3(0.0, 0.0, 3.0), vec3(vuv, -1.));
  
  Camera(R_, vec3(0., 0., 1.), vec3(0., 1., 0.), 90.0, (Res.x / Res.y));
  
  float mindist = -1000.0;

	// here comes this importend part unpack the texture
  for (int i = 0; i < vertsCount; i += 3) 
  {

    a = rotate() * texelFetch(uMeshData, ivec2(i, 0), 0);
    b = rotate() * texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(1, 0));
    c = rotate() * texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(2, 0));
    
    if (isTriangle(R_, a.xyz, b.xyz, c.xyz, hit))
    {
      float z = hit.z;
      if (z > mindist) {
        mindist = z;
        SceneCol.rgb = vec3(hit.x, hit.y, 1. - (hit.x - hit.y));
      };
    }
  }
  
  vec3 sky = vec3(0.5, 0.25, 0.1) * (-R_.dir.y - 0.1);
  fragColor.rgb = SceneCol + sky;
  fragColor.a = 1.0;
}`;

    const canvas = document.getElementById('c');
    const gl = canvas.getContext('webgl2', {
        alpha: !1,
        depth: !1,
        stencil: !1,
        antialias: !1,
        premultipliedAlpha: !1,
        presereDrawingBuffer: !1,
        failIfMajorPerformanceCaveat: !1
    });

    const { width, height } = canvas.getBoundingClientRect();
    gl.canvas.width = width;
    gl.canvas.height = height;

    // init
    const P = gl.createProgram();

    const Fp = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(Fp, fs);
    gl.compileShader(Fp);
    if (!gl.getShaderParameter(Fp, gl.COMPILE_STATUS)) throw '! F r a g: ' + gl.getShaderInfoLog(Fp);
    gl.attachShader(P, Fp);

    const Vp = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(Vp, vs);
    gl.compileShader(Vp);
    if (!gl.getShaderParameter(Vp, gl.COMPILE_STATUS)) throw '! V e r t: ' + gl.getShaderInfoLog(Vp);
    gl.attachShader(P, Vp);

    // link use program
    gl.linkProgram(P);
    gl.useProgram(P);

    // uniform location
    const time_loc = gl.getUniformLocation(P, 'time');
    const res_loc = gl.getUniformLocation(P, 'Res');
    const uLvertices = gl.getUniformLocation(P, 'vertsCount');
    const uLSr = gl.getUniformLocation(P, 'uMeshData');
    const mouse_loc = gl.getUniformLocation(P, 'mouse');

    // free resources
    gl.detachShader(P, Fp);
    gl.detachShader(P, Vp);
    gl.deleteProgram(P);

    // fullscreen quad
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    gl.bufferData(gl.ARRAY_BUFFER, new Int8Array([-3, 1, 1, -3, 1, 1]), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(0);
    gl.vertexAttribPointer(0, 2, gl.BYTE, !1, 0, 0);
    gl.bindVertexArray(null);

    // bind texture
    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);


    // blender 2.79 Icosphere
    // export -> *.raw (needs to be enable first under settings)
    const verts = [
        0.000000, 0.000000, -1.000000, 0.425323, -0.309011, -0.850654, -0.162456, -0.499995, -0.850654,
        0.723607, -0.525725, -0.447220, 0.425323, -0.309011, -0.850654, 0.850648, 0.000000, -0.525736,
        0.000000, 0.000000, -1.000000, -0.162456, -0.499995, -0.850654, -0.525730, 0.000000, -0.850652,
        0.000000, 0.000000, -1.000000, -0.525730, 0.000000, -0.850652, -0.162456, 0.499995, -0.850654,
        0.000000, 0.000000, -1.000000, -0.162456, 0.499995, -0.850654, 0.425323, 0.309011, -0.850654,
        0.723607, -0.525725, -0.447220, 0.850648, 0.000000, -0.525736, 0.951058, -0.309013, 0.000000,
        -0.276388, -0.850649, -0.447220, 0.262869, -0.809012, -0.525738, 0.000000, -1.000000, 0.000000,
        -0.894426, 0.000000, -0.447216, -0.688189, -0.499997, -0.525736, -0.951058, -0.309013, 0.000000,
        -0.276388, 0.850649, -0.447220, -0.688189, 0.499997, -0.525736, -0.587786, 0.809017, 0.000000,
        0.723607, 0.525725, -0.447220, 0.262869, 0.809012, -0.525738, 0.587786, 0.809017, 0.000000,
        0.723607, -0.525725, -0.447220, 0.951058, -0.309013, 0.000000, 0.587786, -0.809017, 0.000000,
        -0.276388, -0.850649, -0.447220, 0.000000, -1.000000, 0.000000, -0.587786, -0.809017, 0.000000,
        -0.894426, 0.000000, -0.447216, -0.951058, -0.309013, 0.000000, -0.951058, 0.309013, 0.000000,
        -0.276388, 0.850649, -0.447220, -0.587786, 0.809017, 0.000000, 0.000000, 1.000000, 0.000000,
        0.723607, 0.525725, -0.447220, 0.587786, 0.809017, 0.000000, 0.951058, 0.309013, 0.000000,
        0.276388, -0.850649, 0.447220, 0.688189, -0.499997, 0.525736, 0.162456, -0.499995, 0.850654,
        -0.723607, -0.525725, 0.447220, -0.262869, -0.809012, 0.525738, -0.425323, -0.309011, 0.850654,
        -0.723607, 0.525725, 0.447220, -0.850648, 0.000000, 0.525736, -0.425323, 0.309011, 0.850654,
        0.276388, 0.850649, 0.447220, -0.262869, 0.809012, 0.525738, 0.162456, 0.499995, 0.850654,
        0.894426, 0.000000, 0.447216, 0.688189, 0.499997, 0.525736, 0.525730, 0.000000, 0.850652,
        0.525730, 0.000000, 0.850652, 0.162456, 0.499995, 0.850654, 0.000000, 0.000000, 1.000000,
        0.525730, 0.000000, 0.850652, 0.688189, 0.499997, 0.525736, 0.162456, 0.499995, 0.850654,
        0.688189, 0.499997, 0.525736, 0.276388, 0.850649, 0.447220, 0.162456, 0.499995, 0.850654,
        0.162456, 0.499995, 0.850654, -0.425323, 0.309011, 0.850654, 0.000000, 0.000000, 1.000000,
        0.162456, 0.499995, 0.850654, -0.262869, 0.809012, 0.525738, -0.425323, 0.309011, 0.850654,
        -0.262869, 0.809012, 0.525738, -0.723607, 0.525725, 0.447220, -0.425323, 0.309011, 0.850654,
        -0.425323, 0.309011, 0.850654, -0.425323, -0.309011, 0.850654, 0.000000, 0.000000, 1.000000,
        -0.425323, 0.309011, 0.850654, -0.850648, 0.000000, 0.525736, -0.425323, -0.309011, 0.850654,
        -0.850648, 0.000000, 0.525736, -0.723607, -0.525725, 0.447220, -0.425323, -0.309011, 0.850654,
        -0.425323, -0.309011, 0.850654, 0.162456, -0.499995, 0.850654, 0.000000, 0.000000, 1.000000,
        -0.425323, -0.309011, 0.850654, -0.262869, -0.809012, 0.525738, 0.162456, -0.499995, 0.850654,
        -0.262869, -0.809012, 0.525738, 0.276388, -0.850649, 0.447220, 0.162456, -0.499995, 0.850654,
        0.162456, -0.499995, 0.850654, 0.525730, 0.000000, 0.850652, 0.000000, 0.000000, 1.000000,
        0.162456, -0.499995, 0.850654, 0.688189, -0.499997, 0.525736, 0.525730, 0.000000, 0.850652,
        0.688189, -0.499997, 0.525736, 0.894426, 0.000000, 0.447216, 0.525730, 0.000000, 0.850652,
        0.951058, 0.309013, 0.000000, 0.688189, 0.499997, 0.525736, 0.894426, 0.000000, 0.447216,
        0.951058, 0.309013, 0.000000, 0.587786, 0.809017, 0.000000, 0.688189, 0.499997, 0.525736,
        0.587786, 0.809017, 0.000000, 0.276388, 0.850649, 0.447220, 0.688189, 0.499997, 0.525736,
        0.000000, 1.000000, 0.000000, -0.262869, 0.809012, 0.525738, 0.276388, 0.850649, 0.447220,
        0.000000, 1.000000, 0.000000, -0.587786, 0.809017, 0.000000, -0.262869, 0.809012, 0.525738,
        -0.587786, 0.809017, 0.000000, -0.723607, 0.525725, 0.447220, -0.262869, 0.809012, 0.525738,
        -0.951058, 0.309013, 0.000000, -0.850648, 0.000000, 0.525736, -0.723607, 0.525725, 0.447220,
        -0.951058, 0.309013, 0.000000, -0.951058, -0.309013, 0.000000, -0.850648, 0.000000, 0.525736,
        -0.951058, -0.309013, 0.000000, -0.723607, -0.525725, 0.447220, -0.850648, 0.000000, 0.525736,
        -0.587786, -0.809017, 0.000000, -0.262869, -0.809012, 0.525738, -0.723607, -0.525725, 0.447220,
        -0.587786, -0.809017, 0.000000, 0.000000, -1.000000, 0.000000, -0.262869, -0.809012, 0.525738,
        0.000000, -1.000000, 0.000000, 0.276388, -0.850649, 0.447220, -0.262869, -0.809012, 0.525738,
        0.587786, -0.809017, 0.000000, 0.688189, -0.499997, 0.525736, 0.276388, -0.850649, 0.447220,
        0.587786, -0.809017, 0.000000, 0.951058, -0.309013, 0.000000, 0.688189, -0.499997, 0.525736,
        0.951058, -0.309013, 0.000000, 0.894426, 0.000000, 0.447216, 0.688189, -0.499997, 0.525736,
        0.587786, 0.809017, 0.000000, 0.000000, 1.000000, 0.000000, 0.276388, 0.850649, 0.447220,
        0.587786, 0.809017, 0.000000, 0.262869, 0.809012, -0.525738, 0.000000, 1.000000, 0.000000,
        0.262869, 0.809012, -0.525738, -0.276388, 0.850649, -0.447220, 0.000000, 1.000000, 0.000000,
        -0.587786, 0.809017, 0.000000, -0.951058, 0.309013, 0.000000, -0.723607, 0.525725, 0.447220,
        -0.587786, 0.809017, 0.000000, -0.688189, 0.499997, -0.525736, -0.951058, 0.309013, 0.000000,
        -0.688189, 0.499997, -0.525736, -0.894426, 0.000000, -0.447216, -0.951058, 0.309013, 0.000000,
        -0.951058, -0.309013, 0.000000, -0.587786, -0.809017, 0.000000, -0.723607, -0.525725, 0.447220,
        -0.951058, -0.309013, 0.000000, -0.688189, -0.499997, -0.525736, -0.587786, -0.809017, 0.000000,
        -0.688189, -0.499997, -0.525736, -0.276388, -0.850649, -0.447220, -0.587786, -0.809017, 0.000000,
        0.000000, -1.000000, 0.000000, 0.587786, -0.809017, 0.000000, 0.276388, -0.850649, 0.447220,
        0.000000, -1.000000, 0.000000, 0.262869, -0.809012, -0.525738, 0.587786, -0.809017, 0.000000,
        0.262869, -0.809012, -0.525738, 0.723607, -0.525725, -0.447220, 0.587786, -0.809017, 0.000000,
        0.951058, -0.309013, 0.000000, 0.951058, 0.309013, 0.000000, 0.894426, 0.000000, 0.447216,
        0.951058, -0.309013, 0.000000, 0.850648, 0.000000, -0.525736, 0.951058, 0.309013, 0.000000,
        0.850648, 0.000000, -0.525736, 0.723607, 0.525725, -0.447220, 0.951058, 0.309013, 0.000000,
        0.425323, 0.309011, -0.850654, 0.262869, 0.809012, -0.525738, 0.723607, 0.525725, -0.447220,
        0.425323, 0.309011, -0.850654, -0.162456, 0.499995, -0.850654, 0.262869, 0.809012, -0.525738,
        -0.162456, 0.499995, -0.850654, -0.276388, 0.850649, -0.447220, 0.262869, 0.809012, -0.525738,
        -0.162456, 0.499995, -0.850654, -0.688189, 0.499997, -0.525736, -0.276388, 0.850649, -0.447220,
        -0.162456, 0.499995, -0.850654, -0.525730, 0.000000, -0.850652, -0.688189, 0.499997, -0.525736,
        -0.525730, 0.000000, -0.850652, -0.894426, 0.000000, -0.447216, -0.688189, 0.499997, -0.525736,
        -0.525730, 0.000000, -0.850652, -0.688189, -0.499997, -0.525736, -0.894426, 0.000000, -0.447216,
        -0.525730, 0.000000, -0.850652, -0.162456, -0.499995, -0.850654, -0.688189, -0.499997, -0.525736,
        -0.162456, -0.499995, -0.850654, -0.276388, -0.850649, -0.447220, -0.688189, -0.499997, -0.525736,
        0.850648, 0.000000, -0.525736, 0.425323, 0.309011, -0.850654, 0.723607, 0.525725, -0.447220,
        0.850648, 0.000000, -0.525736, 0.425323, -0.309011, -0.850654, 0.425323, 0.309011, -0.850654,
        0.425323, -0.309011, -0.850654, 0.000000, 0.000000, -1.000000, 0.425323, 0.309011, -0.850654,
        -0.162456, -0.499995, -0.850654, 0.262869, -0.809012, -0.525738, -0.276388, -0.850649, -0.447220,
        -0.162456, -0.499995, -0.850654, 0.425323, -0.309011, -0.850654, 0.262869, -0.809012, -0.525738,
        0.425323, -0.309011, -0.850654, 0.723607, -0.525725, -0.447220, 0.262869, -0.809012, -0.525738,
    ];
    const meshVerts = new Float32Array(verts);
    const vertsLenght = meshVerts.length / 3;
    gl.uniform1i(uLvertices, vertsLenght);
    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB32F, vertsLenght, 1, 0, gl.RGB, gl.FLOAT, meshVerts);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    // mouse click
    let mousePosition = [0, 0];
    gl.canvas.addEventListener('mousemove', (e) => {
        if (!e.buttons) return;
        if (e.buttons == 1) mousePosition = [e.clientX * .01, e.clientY * .01];
    }, !1);

    // animation
    const draw = (clock) => {
        clock *= 0.001;
        gl.viewport(0.0, 0.0, gl.drawingBufferWidth, gl.drawingBufferHeight);
        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.uniform1i(uLSr, 0);
        gl.uniform1f(time_loc, clock);
        gl.uniform2f(mouse_loc, mousePosition[0], mousePosition[1]);
        gl.uniform2f(res_loc, width, height);
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
        requestAnimationFrame(draw);
    };
    requestAnimationFrame(draw);
})()
<canvas id="c"></canvas>