2012-02-28 29 views
17

Tôi đang tìm hiểu cách hiển thị khối lượng bằng thuật toán truyền tia. Tôi đã tìm thấy một bản demo và bài giảng tốt trong here. nhưng vấn đề là tôi có một card đồ họa ATI thay vì nVidia mà làm cho tôi không thể sử dụng các shader cg trong bản demo, vì vậy tôi muốn thay đổi shader cg để glsl shader. Tôi đã trải qua cuốn sách đỏ (7 ấn bản) của OpenGL, nhưng không quen thuộc với glsl và cg. không ai có thể giúp tôi thay đổi shader cg trong demo để glsl? hoặc là có bất kỳ tài liệu nào cho bản demo đơn giản nhất về hiển thị khối lượng bằng cách sử dụng tính năng truyền tia (tất nhiên là trong glsl). here là trình đổ bóng cg của bản trình diễn. và nó có thể hoạt động trên card đồ họa nVidia của bạn tôi. những gì hầu hết khó hiểu cho tôi là tôi không biết làm thế nào để dịch các phần nhập cảnh của cg để GLSL, ví dụ:hiển thị khối lượng (sử dụng glsl) với thuật toán tạo đĩa quang

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

còn gì nữa, tôi có thể viết một chương trình ràng buộc đối tượng 2 texture với đơn vị 2 texture đến đổ bóng với điều kiện là tôi gán hai texcoord khi vẽ màn hình, ví dụ

glMultiTexCoord2f(GL_TEXTURE0, 1.0, 0.0);

glMultiTexCoord2f(GL_TEXTURE1, 1.0, 0.0);

Trong bản demo chương trình sẽ liên kết với hai kết cấu (một 2D cho backface_buffer một 3D cho volume texture), nhưng chỉ với một đơn vị kết cấu như glMultiTexCoord3f(GL_TEXTURE1, x, y, z); Tôi nghĩ đơn vị GL_TEXTURE1 là dành cho kết cấu âm lượng, nhưng cái nào (đơn vị texure) là dành cho backface_buffer? theo như tôi biết để ràng buộc obj kết cấu trong bóng đổ, tôi phải có đơn vị kết cấu để liên kết ví dụ:

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); 

chương trình được biên soạn tốt và được liên kết ok. nhưng tôi chỉ nhận được -1 của cả ba vị trí (texloc, volume_texloc và stepsizeloc). Tôi biết nó có thể được tối ưu hóa. bất cứ ai có thể giúp tôi dịch các shader cg để glsl shader?

Edit: Nếu bạn đang quan tâm đến hiện đại thực hiện OpenGL API (mã nguồn C++) với GLSL: Volume_Rendering_Using_GLSL

+0

Trình tạo bóng Cg cũng hoạt động tốt trên ATi/AMD khi chúng hoạt động trên nVidia (tương đối tương đối, vì thời gian chạy Cg có * nhiều mã lỗi trên máy chủ). – ssube

+0

Chỉ cần nhắc nhở: Trình biên dịch Cg có thể phát ra mã GLSL. Cũng có thể sử dụng Cg với thẻ AMD/ATI. Chỉ có một vài thứ cụ thể của NVidia sẽ không hoạt động, và hiệu suất sẽ hơi yếu. – datenwolf

+0

@datenwolf thực sự? Tôi sẽ cho nó nó một cơ hội. Tôi tự hỏi làm thế nào để phát ra mã glsl? – toolchainX

Trả lời

14

Vấn đề giải quyết. các glsl version của demo:

vertex

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; 
} 

fragment shader

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; 
} 

nếu bạn thấy bản gốc shader của cg chỉ có một sự khác biệt nhỏ giữa cg và GLSL . phần khó khăn nhất để dịch các bản demo lên phiên bản GLSL là chức năng cg trong OpenGL như:

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

tóm lược quá trình đơn vị kết cấu và kích hoạt multitexture (sử dụng glActiveTexture) và vô hiệu hóa, mà là rất quan trọng trong việc bản demo này vì nó đã sử dụng đường ống cố định cũng như đường ống lập trình được. đây là phân đoạn chính thay đổi trong hàm void raycasting_pass() của chính.cpp của bản demo tại Peter Triers GPU raycasting hướng dẫn:

chức năng 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); 
} 

Vậy là xong.

Các vấn đề liên quan