opengl glsl demo raycasting volume-rendering

opengl - Representación de volumen(usando glsl) con algoritmo de conversión de rayos



demo raycasting (1)

Problema resuelto. La Volume_Rendering_Using_GLSL de la here :

sombreador de vértice

void main() { gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; //gl_FrontColor = gl_Color; gl_TexCoord[2] = gl_Position; gl_TexCoord[0] = gl_MultiTexCoord1; gl_TexCoord[1] = gl_Color; }

fragmento de sombreado

uniform sampler2D tex; uniform sampler3D volume_tex; uniform float stepsize; void main() { vec2 texc = ((gl_TexCoord[2].xy/gl_TexCoord[2].w) + 1) / 2; vec4 start = gl_TexCoord[0]; vec4 back_position = texture2D(tex, texc); vec3 dir = vec3(0.0); dir.x = back_position.x - start.x; dir.y = back_position.y - start.y; dir.z = back_position.z - start.z; float len = length(dir.xyz); // the length from front to back is calculated and used to terminate the ray vec3 norm_dir = normalize(dir); float delta = stepsize; vec3 delta_dir = norm_dir * delta; float delta_dir_len = length(delta_dir); vec3 vect = start.xyz; vec4 col_acc = vec4(0,0,0,0); // The dest color float alpha_acc = 0.0; // The dest alpha for blending float length_acc = 0.0; vec4 color_sample; // The src color float alpha_sample; // The src alpha for(int i = 0; i < 450; i++) { color_sample = texture3D(volume_tex,vect); // why multiply the stepsize? alpha_sample = color_sample.a*stepsize; // why multply 3? col_acc += (1.0 - alpha_acc) * color_sample * alpha_sample*3 ; alpha_acc += alpha_sample; vect += delta_dir; length_acc += delta_dir_len; if(length_acc >= len || alpha_acc > 1.0) break; // terminate if opacity > 1 or the ray is outside the volume } gl_FragColor = col_acc; }

Si has visto el here original de cg, solo hay una pequeña diferencia entre cg y glsl. la parte más difícil de traducir la versión demo a glsl es que la función cg en el opengl como:

param = cgGetNamedParameter(program, par); cgGLSetTextureParameter(param, tex); cgGLEnableTextureParameter(param);

encapsule el proceso de la unidad de textura y la activación multitextura (utilizando glActiveTexture ) y la desactivación, lo cual es muy importante en esta demostración, ya que utiliza la tubería fija y la tubería programable. Aquí está el segmento clave cambiado en la función void raycasting_pass() de main.cpp de la demostración en el tutorial de difusión de rayos de la GPU Peter Triers:

función raycasting_pass

void raycasting_pass() { // specify which texture to bind glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, final_image, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glUseProgram(p); glUniform1f(stepsizeIndex, stepsize); glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, volume_texture); glUniform1i(volume_tex, 1); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, backface_buffer); glUniform1i(tex, 0); glUseProgram(p); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); drawQuads(1.0,1.0, 1.0); // Draw a cube glDisable(GL_CULL_FACE); glUseProgram(0); // recover to use only one texture unit as for the fixed pipeline glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_3D); glActiveTexture(GL_TEXTURE0); }

Eso es.

Estoy aprendiendo la representación de volumen utilizando el algoritmo de lanzamiento de rayos. He encontrado una buena demostración y tutorial here . pero el problema es que tengo una tarjeta gráfica ATI en lugar de nVidia que me impide utilizar el sombreador cg en la demostración, así que quiero cambiar el sombreador cg a glsl shader. He revisado el libro rojo (7 edición) de OpenGL, pero no estoy familiarizado con glsl y cg. ¿Alguien puede ayudarme a cambiar el sombreador cg en la demo a glsl? o hay algún material para la demostración más simple de la representación de volumen utilizando el lanzamiento de rayos (por supuesto, en glsl). here está el shader cg de la demo. y puede funcionar en la tarjeta gráfica nVidia de mi amigo. lo que más me confunde es que no sé cómo traducir la parte de entrada de cg a glsl, por ejemplo:

struct vertex_fragment { float4 Position : POSITION; // For the rasterizer float4 TexCoord : TEXCOORD0; float4 Color : TEXCOORD1; float4 Pos : TEXCOORD2; };

lo que es más, puedo escribir un objeto de textura de enlace de programa 2 con 2 unidades de textura al sombreador siempre que asigne dos texcoord al dibujar la pantalla, por ejemplo

glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);

glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);

En la demostración, el programa se unirá a dos texturas (una 2D para backface_buffer una 3D para la volume texture ), pero con una sola unidad de textura como glMultiTexCoord3f(GL_TEXTURE1, x, y, z); Creo que la unidad GL_TEXTURE1 es para la textura del volumen, pero ¿cuál (unidad de texure) es para el backface_buffer ? Por lo que sé, para vincular la textura obj en un sombreador, debo obtener una unidad de textura para enlazar, por ejemplo:

glLinkProgram(p); texloc = glGetUniformLocation(p, "tex"); volume_texloc = glGetUniformLocation(p, "volume_tex"); stepsizeloc = glGetUniformLocation(p, "stepsize"); glUseProgram(p); glUniform1i(texloc, 0); glUniform1i(volume_texloc, 1); glUniform1f(stepsizeloc, stepsize); //When rendering an object with this program. glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, backface_buffer); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_3D, volume_texture);

El programa está bien compilado y enlazado. pero solo obtuve -1 de las tres ubicaciones (texloc, volume_texloc y stepsizeloc). Sé que puede ser optimizado. ¿Alguien puede ayudarme a traducir el sombreador cg a glsl shader?

Edición: si estás interesado en la implementación moderna de la API de OpenGL (código fuente de C ++) con glsl: Volume_Rendering_Using_GLSL