GPU 射线投射(单通道),具有球坐标中的 3D 纹理

2023-12-04

我正在实现一种体积渲染算法“GPU 光线投射单通道”。为此,我使用强度值的浮点数组作为 3d 纹理(此 3d 纹理描述了球坐标中的常规 3d 网格)。

这里有数组值的示例:

   75.839354473071637,     
   64.083049468866022,    
   65.253933716444365,     
   79.992431196592577,     
   84.411485976957096,     
   0.0000000000000000,     
   82.020319431382831,     
   76.808403454586994,     
   79.974774618246158,     
   0.0000000000000000,     
   91.127273013466336,     
   84.009956557448433,     
   90.221356094672814,     
   87.567422484025627,     
   71.940263118478072,     
   0.0000000000000000,     
   0.0000000000000000,     
   74.487058398181944,
   ..................,
   ..................

(完整数据如下:[链接](https://drive.google.com/file/d/1lbXzRucUseF-ITzFgxqeLTd0WglJJOoz/view?usp=sharing))

球形网格的尺寸为(r,theta,phi)=(384,15,768),这是加载纹理的输入格式:

glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, 384, 15, 768, 0, GL_RED, GL_FLOAT, dataArray)

这是我的可视化图像:

image

问题是可视化应该是一个磁盘,或者至少是一个类似的形式。

我认为问题是我没有正确指定纹理的坐标(在球面坐标中)。

这是顶点着色器代码:

  #version 330 core

layout(location = 0) in vec3 vVertex; //object space vertex position

//uniform
 uniform mat4 MVP;   //combined modelview projection matrix

 smooth out vec3 vUV; //3D texture coordinates for texture lookup in   the fragment shader

void main()
{  
    //get the clipspace position 
     gl_Position = MVP*vec4(vVertex.xyz,1);

    //get the 3D texture coordinates by adding (0.5,0.5,0.5) to the object space 
    //vertex position. Since the unit cube is at origin (min: (-0.5,-0.5,-0.5) and max: (0.5,0.5,0.5))
    //adding (0.5,0.5,0.5) to the unit cube object space position gives us values from (0,0,0) to 
    //(1,1,1)
    vUV = vVertex + vec3(0.5);
}

这是片段着色器代码:

  #version 330 core

layout(location = 0) out vec4 vFragColor;   //fragment shader output

smooth in vec3 vUV;             //3D texture coordinates  form vertex shader 
                                 //interpolated by rasterizer

//uniforms
uniform sampler3D   volume;     //volume dataset
uniform vec3        camPos;     //camera position
uniform vec3        step_size;  //ray step size 




//constants
const int MAX_SAMPLES = 300;    //total samples for each ray march step
const vec3 texMin = vec3(0);    //minimum texture access coordinate
const vec3 texMax = vec3(1);    //maximum texture access coordinate





    vec4 colour_transfer(float intensity)
{

    vec3 high = vec3(100.0, 20.0, 10.0);
   // vec3 low = vec3(0.0, 0.0, 0.0);
   float alpha = (exp(intensity) - 1.0) / (exp(1.0) - 1.0);
   return vec4(intensity * high, alpha);

}



void main()
{ 
//get the 3D texture coordinates for lookup into the volume dataset
vec3 dataPos = vUV;


//Getting the ray marching direction:
//get the object space position by subracting 0.5 from the
//3D texture coordinates. Then subtraact it from camera position
//and normalize to get the ray marching direction
vec3 geomDir = normalize((vUV-vec3(0.5)) - camPos); 

//multiply the raymarching direction with the step size to get the
//sub-step size we need to take at each raymarching step
vec3 dirStep = geomDir * step_size; 

//flag to indicate if the raymarch loop should terminate
bool stop = false; 

//for all samples along the ray
for (int i = 0; i < MAX_SAMPLES; i++) {
    // advance ray by dirstep
    dataPos = dataPos + dirStep;



    stop = dot(sign(dataPos-texMin),sign(texMax-dataPos)) < 3.0;

    //if the stopping condition is true we brek out of the ray marching loop
    if (stop) 
        break;
    // data fetching from the red channel of volume texture
    float sample = texture(volume, dataPos).r;  

     vec4 c = colour_transfer(sample);

    vFragColor.rgb = c.a * c.rgb + (1 - c.a) * vFragColor.a * vFragColor.rgb;
    vFragColor.a = c.a + (1 - c.a) * vFragColor.a;

    //early ray termination
    //if the currently composited colour alpha is already fully saturated
    //we terminated the loop
    if( vFragColor.a>0.99)
        break;
} 


}

我如何指定坐标以便在球坐标中可视化 3D 纹理中的信息?

UPDATE:

顶点着色器:

#version 330 core

layout(location = 0) in vec3 vVertex; //object space vertex position

//uniform
uniform mat4 MVP;   //combined modelview projection matrix

smooth out vec3 vUV; //3D texture coordinates for texture lookup in the             fragment shader



void main()
{  
    //get the clipspace position 
    gl_Position = MVP*vec4(vVertex.xyz,1);

     //get the 3D texture coordinates by adding (0.5,0.5,0.5) to the object     space 
    //vertex position. Since the unit cube is at origin (min: (-0.5,-   0.5,-0.5) and max: (0.5,0.5,0.5))
    //adding (0.5,0.5,0.5) to the unit cube object space position gives    us values from (0,0,0) to 
//(1,1,1)
vUV = vVertex + vec3(0.5);
}

和片段着色器:

#version 330 core
#define Pi 3.1415926535897932384626433832795

layout(location = 0) out vec4 vFragColor;   //fragment shader output

smooth in vec3 vUV;             //3D texture coordinates form vertex shader 
                            //interpolated by rasterizer

//uniforms
uniform sampler3D   volume;     //volume dataset
uniform vec3        camPos;     //camera position
uniform vec3        step_size;  //ray step size 




//constants
const int MAX_SAMPLES = 200;    //total samples for each ray march step
const vec3 texMin = vec3(0);    //minimum texture access coordinate
const vec3 texMax = vec3(1);    //maximum texture access coordinate

// transfer function that asigned a color and alpha from sample    intensity
vec4 colour_transfer(float intensity)
{

    vec3 high = vec3(100.0, 20.0, 10.0);
    // vec3 low = vec3(0.0, 0.0, 0.0);
    float alpha = (exp(intensity) - 1.0) / (exp(1.0) - 1.0);

    return vec4(intensity * high, alpha);

}


// this function transform vector in spherical coordinates from cartesian
vec3 cart2Sphe(vec3 cart){
    vec3 sphe;
    sphe.x = sqrt(cart.x*cart.x+cart.y*cart.y+cart.z*cart.z);
    sphe.z = atan(cart.y/cart.x);
    sphe.y = atan(sqrt(cart.x*cart.x+cart.y*cart.y)/cart.z);
    return sphe;
}


void main()
{ 
    //get the 3D texture coordinates for lookup into the volume dataset
    vec3 dataPos = vUV;


    //Getting the ray marching direction:
    //get the object space position by subracting 0.5 from the
    //3D texture coordinates. Then subtraact it from camera position
    //and normalize to get the ray marching direction
    vec3 vec=(vUV-vec3(0.5)); 
    vec3 spheVec=cart2Sphe(vec); // transform position to spherical
    vec3 sphePos=cart2Sphe(camPos); //transform camPos to spherical
    vec3 geomDir= normalize(spheVec-sphePos); // ray direction


    //multiply the raymarching direction with the step size to get the
    //sub-step size we need to take at each raymarching step
    vec3 dirStep = geomDir * step_size ; 
    //flag to indicate if the raymarch loop should terminate

    //for all samples along the ray
    for (int i = 0; i < MAX_SAMPLES; i++) {
        // advance ray by dirstep
        dataPos = dataPos + dirStep;


        float sample;

        convert texture coordinates 
        vec3 spPos;
        spPos.x=dataPos.x/384;
        spPos.y=(dataPos.y+(Pi/2))/Pi;
        spPos.z=dataPos.z/(2*Pi);

        // get value from texture
         sample = texture(volume,dataPos).r;
         vec4 c = colour_transfer(sample)



        // alpha blending  function
         vFragColor.rgb = c.a * c.rgb + (1 - c.a) * vFragColor.a *      vFragColor.rgb;
        vFragColor.a = c.a + (1 - c.a) * vFragColor.a;


        if( vFragColor.a>1.0)
        break;
    } 

    // vFragColor.rgba = texture(volume,dataPos);
}

这些是生成边界立方体的点:

 glm::vec3 vertices[8] = {glm::vec3(-0.5f, -0.5f, -0.5f),
                                                 glm::vec3(0.5f, -0.5f,   -0.5f),
                                                 glm::vec3(0.5f, 0.5f, -0.5f),
                                                 glm::vec3(-0.5f, 0.5f, -0.5f),
                                                 glm::vec3(-0.5f, -0.5f, 0.5f),
                                                 glm::vec3(0.5f, -0.5f, 0.5f),
                                                 glm::vec3(0.5f, 0.5f, 0.5f),
                                                 glm::vec3(-0.5f, 0.5f, 0.5f)};



    //unit cube indices
    GLushort cubeIndices[36] = {0, 5, 4,
                                                        5, 0, 1,
                                                        3, 7, 6,
                                                        3, 6, 2,
                                                        7, 4, 6,
                                                        6, 4, 5,
                                                        2, 1, 3,
                                                        3, 1, 0,
                                                        3, 0, 7,
                                                        7, 0, 4,
                                                        6, 5, 2,
                                                        2, 5, 1};

这是它生成的可视化效果:

Imgur Imgur1


我不知道你渲染什么以及如何渲染。有许多技术和配置可以实现它们。我通常使用覆盖屏幕/视图的单通道单四边形渲染,而几何图形/场景作为纹理传递。当你的对象是 3D 纹理时,我认为你也应该这样做。这是它的完成方式(假设透视,均匀的球形体素网格作为 3D 纹理):

  1. CPU端代码

    简单地渲染单个QUAD覆盖场景/视图。为了使这个更加简单和精确,我建议您使用球体局部坐标系作为传递给着色器的相机矩阵(它将大大简化光线/球体相交计算)。

  2. Vertex

    在这里,您应该投射/计算每个顶点的光线位置和方向,并将其传递给片段,以便为屏幕/视图上的每个像素进行插值。

    所以相机是通过它的位置(焦点)和视角方向(通常是透视中的Z轴)来描述的。OpenGL)。光线从焦点投射(0,0,0)在相机局部坐标中znear plane (x,y,-znear)也在相机本地坐标中。在哪里x,y是在屏幕/视图不是正方形时应用纵横比校正的像素屏幕位置。

    因此,您只需将这两个点转换为球体局部坐标(仍然是笛卡尔坐标)。

    射线方向只是两点相减......

  3. Fragment

    首先规范化从顶点传递的光线方向(由于插值,它不会是单位向量)。之后,只需从外到内测试球体素网格每个半径的射线/球体相交,以便测试球体rmax to rmax/n where rmax是 3D 纹理可以拥有的最大半径,n是与半径对应的轴的 ids 分辨率r.

    每次点击时将笛卡尔交点位置转换为球坐标。将它们转换为纹理坐标s,t,p并获取体素强度并将其应用到颜色(具体取决于您渲染的内容和方式)。

    所以如果你的纹理坐标是(r,theta,phi)假设phi是经度,角度标准化为<-Pi,Pi> and <0,2*Pi> and rmax是 3D 纹理的最大半径:

    s = r/rmax
    t = (theta+(Pi/2))/Pi
    p = phi/(2*PI)
    

    如果您的球体不透明,则在体素强度不为空的第一次命中时停止。否则更新光线开始位置并再次执行整个项目符号,直到光线离开场景 BBOX 或没有发生相交。

    您还可以通过在物体边界命中时分割光线来添加斯涅耳定律(添加反射折射)...

这里有一些相关的QA使用此技术或拥有有效信息可以帮助您实现此目标:

  • GLSL大气散射这与您应该做的几乎相同。
  • 射线和椭球相交精度提高交叉点的数学
  • 弧形磨砂玻璃着色器?次表面散射
  • 通过 3D 网格的 GLSL 背面光线追踪2D 纹理内几何体的反射和折射
  • 通过 3D 体积的 GLSL 背面光线追踪3D 纹理内的 3D 笛卡尔体积

[Edit1] 示例(输入 3D 纹理最终发布后

因此,当我将上面(和评论中)的所有内容放在一起时,我想出了这个。

CPU端代码:

//---------------------------------------------------------------------------
//--- GLSL Raytrace system ver: 1.000 ---------------------------------------
//---------------------------------------------------------------------------
#ifndef _raytrace_spherical_volume_h
#define _raytrace_spherical_volume_h
//---------------------------------------------------------------------------
class SphericalVolume3D
    {
public:
    bool _init;         // has been initiated ?
    GLuint txrvol;      // SphericalVolume3D texture at GPU side
    int xs,ys,zs;

    float eye[16];      // direct camera matrix
    float aspect,focal_length;

    SphericalVolume3D()    { _init=false; txrvol=-1; xs=0; ys=0; zs=0; aspect=1.0; focal_length=1.0; }
    SphericalVolume3D(SphericalVolume3D& a)   { *this=a; }
    ~SphericalVolume3D()   { gl_exit(); }
    SphericalVolume3D* operator = (const SphericalVolume3D *a) { *this=*a; return this; }
    //SphericalVolume3D* operator = (const SphericalVolume3D &a) { ...copy... return this; }

    // init/exit
    void gl_init();
    void gl_exit();

    // render
    void glsl_draw(GLint prog_id);
    };
//---------------------------------------------------------------------------
void SphericalVolume3D::gl_init()
    {
    if (_init) return; _init=true;
    // load 3D texture from file into CPU side memory
    int hnd,siz; BYTE *dat;
    hnd=FileOpen("Texture3D_F32.dat",fmOpenRead);
    siz=FileSeek(hnd,0,2);
        FileSeek(hnd,0,0);
    dat=new BYTE[siz];
        FileRead(hnd,dat,siz);
        FileClose(hnd);
    if (0)
        {
        int i,n=siz/sizeof(GLfloat);
        GLfloat *p=(GLfloat*)dat;
        for (i=0;i<n;i++) p[i]=100.5;
        }

    // copy it to GPU as 3D texture
//  glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
//  glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
//  glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
    glGenTextures(1,&txrvol);
    glEnable(GL_TEXTURE_3D);
    glBindTexture(GL_TEXTURE_3D,txrvol);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
    xs=384;
    ys= 15;
    zs=768;
    glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, xs,ys,zs, 0, GL_RED, GL_FLOAT, dat);
    glBindTexture(GL_TEXTURE_3D,0);
    glDisable(GL_TEXTURE_3D);
    delete[] dat;
    }
//---------------------------------------------------------------------------
void SphericalVolume3D::gl_exit()
    {
    if (!_init) return; _init=false;
    glDeleteTextures(1,&txrvol);
    }
//---------------------------------------------------------------------------
void SphericalVolume3D::glsl_draw(GLint prog_id)
    {
    GLint ix;
    const int txru_vol=0;
    glUseProgram(prog_id);
    // uniforms
    ix=glGetUniformLocation(prog_id,"zoom"        ); glUniform1f(ix,1.0);
    ix=glGetUniformLocation(prog_id,"aspect"      ); glUniform1f(ix,aspect);
    ix=glGetUniformLocation(prog_id,"focal_length"); glUniform1f(ix,focal_length);
    ix=glGetUniformLocation(prog_id,"vol_xs"      ); glUniform1i(ix,xs);
    ix=glGetUniformLocation(prog_id,"vol_ys"      ); glUniform1i(ix,ys);
    ix=glGetUniformLocation(prog_id,"vol_zs"      ); glUniform1i(ix,zs);
    ix=glGetUniformLocation(prog_id,"vol_txr"     ); glUniform1i(ix,txru_vol);
    ix=glGetUniformLocation(prog_id,"tm_eye"      ); glUniformMatrix4fv(ix,1,false,eye);

    glActiveTexture(GL_TEXTURE0+txru_vol);
    glEnable(GL_TEXTURE_3D);
    glBindTexture(GL_TEXTURE_3D,txrvol);

    // this should be a VAO/VBO
    glColor4f(1.0,1.0,1.0,1.0);
    glBegin(GL_QUADS);
    glVertex2f(-1.0,-1.0);
    glVertex2f(-1.0,+1.0);
    glVertex2f(+1.0,+1.0);
    glVertex2f(+1.0,-1.0);
    glEnd();

    glActiveTexture(GL_TEXTURE0+txru_vol);
    glBindTexture(GL_TEXTURE_3D,0);
    glDisable(GL_TEXTURE_3D);
    glUseProgram(0);
    }
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------

当 GL 已经初始化时,在应用程序启动时调用 init,在应用程序退出之前退出,同时 GL 仍然工作并在需要时绘制...代码是C++/VCL基于 so 端口到您的环境(文件访问、字符串等)。我还使用二进制形式的 3D 纹理,因为加载 85MByte ASCII 文件对我来说有点太多了。

Vertex:

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
uniform float aspect;
uniform float focal_length;
uniform float zoom;
uniform mat4x4 tm_eye;
layout(location=0) in vec2 pos;

out smooth vec3 ray_pos;    // ray start position
out smooth vec3 ray_dir;    // ray start direction
//------------------------------------------------------------------
void main(void)
    {
    vec4 p;
    // perspective projection
    p=tm_eye*vec4(pos.x/(zoom*aspect),pos.y/zoom,0.0,1.0);
    ray_pos=p.xyz;
    p-=tm_eye*vec4(0.0,0.0,-focal_length,1.0);
    ray_dir=normalize(p.xyz);
    gl_Position=vec4(pos,0.0,1.0);
    }
//------------------------------------------------------------------

它或多或少是体积射线追踪器链接的副本。

分段:

//------------------------------------------------------------------
#version 420 core
//------------------------------------------------------------------
// Ray tracer ver: 1.000
//------------------------------------------------------------------
in smooth vec3      ray_pos;    // ray start position
in smooth vec3      ray_dir;    // ray start direction
uniform int         vol_xs,     // texture resolution
                    vol_ys,
                    vol_zs;
uniform sampler3D   vol_txr;    // scene mesh data texture
out layout(location=0) vec4 frag_col;
//---------------------------------------------------------------------------
// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2
float view_depth_l0=-1.0,view_depth_l1=-1.0;
bool _view_depth(vec3 _p0,vec3 _dp,vec3 _r)
    {
    double a,b,c,d,l0,l1;
    dvec3 p0,dp,r;
    p0=dvec3(_p0);
    dp=dvec3(_dp);
    r =dvec3(_r );
    view_depth_l0=-1.0;
    view_depth_l1=-1.0;
    a=(dp.x*dp.x*r.x)
     +(dp.y*dp.y*r.y)
     +(dp.z*dp.z*r.z); a*=2.0;
    b=(p0.x*dp.x*r.x)
     +(p0.y*dp.y*r.y)
     +(p0.z*dp.z*r.z); b*=2.0;
    c=(p0.x*p0.x*r.x)
     +(p0.y*p0.y*r.y)
     +(p0.z*p0.z*r.z)-1.0;
    d=((b*b)-(2.0*a*c));
    if (d<0.0) return false;
    d=sqrt(d);
    l0=(-b+d)/a;
    l1=(-b-d)/a;
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
    if (l0<0.0)          { a=l0; l0=l1; l1=a; }
    if (l0<0.0) return false;
    view_depth_l0=float(l0);
    view_depth_l1=float(l1);
    return true;
    }
//---------------------------------------------------------------------------
const float pi =3.1415926535897932384626433832795;
const float pi2=6.2831853071795864769252867665590;
float atanxy(float x,float y) // atan2 return < 0 , 2.0*M_PI >
        {
        int sx,sy;
        float a;
        const float _zero=1.0e-30;
        sx=0; if (x<-_zero) sx=-1; if (x>+_zero) sx=+1;
        sy=0; if (y<-_zero) sy=-1; if (y>+_zero) sy=+1;
        if ((sy==0)&&(sx==0)) return 0;
        if ((sx==0)&&(sy> 0)) return 0.5*pi;
        if ((sx==0)&&(sy< 0)) return 1.5*pi;
        if ((sy==0)&&(sx> 0)) return 0;
        if ((sy==0)&&(sx< 0)) return pi;
        a=y/x; if (a<0) a=-a;
        a=atan(a);
        if ((x>0)&&(y>0)) a=a;
        if ((x<0)&&(y>0)) a=pi-a;
        if ((x<0)&&(y<0)) a=pi+a;
        if ((x>0)&&(y<0)) a=pi2-a;
        return a;
        }
//---------------------------------------------------------------------------
void main(void)
    {
    float a,b,r,_rr,c;
    const float dr=1.0/float(vol_ys);       // r step
    const float saturation=1000.0;          // color saturation voxel value
    vec3  rr,p=ray_pos,dp=normalize(ray_dir);
    for (c=0.0,r=1.0;r>1e-10;r-=dr)         // check all radiuses inwards
        {
        _rr=1.0/(r*r); rr=vec3(_rr,_rr,_rr);
        if (_view_depth(p,dp,rr))           // if ray hits sphere
            {
            p+=view_depth_l0*dp;            // shift ray start position to the hit
            a=atanxy(p.x,p.y);              // comvert to spherical a,b,r
            b=asin(p.z/r);
            if (a<0.0) a+=pi2;              // correct ranges...
            b+=0.5*pi;
            a/=pi2;
            b/=pi;
            // here do your stuff
            c=texture(vol_txr,vec3(b,r,a)).r;// fetch voxel
            if (c>saturation){ c=saturation; break; }
            break;
            }
        }
    c/=saturation;

    frag_col=vec4(c,c,c,1.0);
    }
//--------------------------------------------------------------------------- 

它对体积射线追踪器链接进行了轻微修改。

请注意,我假设纹理内的轴是:

latitude,r,longitude

分辨率暗示(经度应该是纬度的双倍分辨率),所以如果它与您的数据不匹配,只需重新排序片段中的轴...我不知道体素单元的值意味着什么,所以我将它们相加为强度/最终颜色的密度,一旦饱和度和达到,光线跟踪就会停止,但你应该计算你想要的东西。

这里预览:

preview

我用的是这个相机矩阵eye for it:

// globals
SphericalVolume3D vol;
// init (GL must be already working)
vol.gl_init();

// render
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-2.5);
glGetFloatv(GL_MODELVIEW_MATRIX,vol.eye);
vol.glsl_draw(prog_id);

glFlush();
SwapBuffers(hdc);

// exit (GL must be still working)
vol.gl_init();

射线/球体命中工作正常,球坐标中的命中位置也正常工作,所以唯一剩下的就是轴顺序和颜色算术......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GPU 射线投射(单通道),具有球坐标中的 3D 纹理 的相关文章

  • 使用 openGL、SOIL 加载图像

    我尝试了很多使用 SOIL 在 openGL 中加载和显示图像的示例 运行下面的源代码时 它仅显示一个没有图像的白色四边形 我尝试打开一个名为 foto 的图像 我将图像文件放在程序的文件夹中 bool keyStates new bool
  • 使用 Opengl 绘制立方体 3D

    我想使用 OpenGL 绘制 3D 立方体这是我的代码如何纠正错误 float ver 8 3 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  • 在 OpenGL 中,为什么 glVertexAttribPointer 要求“指针”参数以 void* 形式传入?

    规格为glVertexAttribPointer如下 void glVertexAttribPointer GLuint index GLint size GLenum type GLboolean normalized GLsizei s
  • QOpenGLFunctions 缺少重要的 OpenGL 函数

    QOpenGLFunctions 似乎缺少重要的函数 例如 glInvalidateFramebuffer 和 glMapBuffer 据我了解 QOpenGLFunctions 加载桌面 OpenGL 函数和 ES 函数的交集 如果是这样
  • OpenGL z轴指向哪里?

    我正在尝试了解 OpenGL 坐标系 我到处都看到它被描述为右撇子 但这与我的经验不符 我尝试绘制一些形状和 3 d 对象 我发现 z 轴显然指向 屏幕 而 x 指向右侧 y 指向上方 这是左手坐标系的描述 我缺少什么 编辑 例如 http
  • gluPerspective 与 gluOrtho2D

    我查看了 MSDN 上关于这两个函数的文档 但是 我不太明白这两个功能之间的区别 一个是用于设置 3D 相机视图 另一个是用于设置 2D 相机视图 如果能得到解答就太好了 预先感谢您的评论 正交投影基本上是没有透视的 3D 投影 本质上 这
  • 为什么我的 FPS 相机一劳永逸地滚动?

    如果我忽略四元数代数的肮脏细节 我想我理解了旋转和平移变换背后的数学 但仍然不明白我做错了什么 为什么我的相机一劳永逸地滚动 更具体地说 我应该如何从相机的方向 旋转矩阵 计算相机视图矩阵 我正在用 Python 编写一个简约的 3d 引擎
  • openGL转png

    我正在尝试将包含大量纹理 没有移动 的 openGL 编辑 我画的卡片 thx unwind 转换为一个 PNG 文件 我可以在框架的另一部分中使用该文件我正在与 有 C 库可以做到这一点吗 thanks 如果您的意思只是 获取由 Open
  • GLSL 棋盘图案

    我想用跳棋来遮蔽四边形 f P 下限 Px 下限 Py mod2 我的四边形是 glBegin GL QUADS glVertex3f 0 0 0 0 glVertex3f 4 0 0 0 glVertex3f 4 4 0 0 glVert
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • SDL 鼠标位置调整大小后裁剪

    我在 SDL 中的鼠标位置上遇到了一些奇怪的行为 如果我将窗口大小调整得更大 则任一鼠标事件的 x y 位置似乎都限制为原始窗口的宽度和高度 如果我缺少一些函数调用来告诉 SDL 鼠标区域的大小已增加 应用程序的相关部分 void Resi
  • 为什么OpenGL使用float而不是double? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • PyQt5 的 OpenGL 模块和版本控制问题(调用不正确的 _QOpenGLFunctions_(ver))

    我一直在努力得到PyQt5 helloGL 示例代码 https github com baoboa pyqt5 blob master examples opengl hellogl py编译 当我尝试构建解决方案时 我得到 Traceb
  • GL_CULL_FACE使所有对象消失

    我正在尝试在 openGL3 3 中创建一些简单的多边形 我有两种类型的对象 具有以下属性 对象 1 10 个顶点 按顺序在下面列出 存储在GL ARRAY BUFFER并使用GL TRIANGLE FAN v x y z w v 0 0
  • GLSL NVidia 方形神器

    当 GLSL 着色器在以下 GPU 上生成不正确的图像时 我遇到了问题 GT 430 GT 770 GTX 570显卡760 但在这些上正常工作 英特尔高清显卡 2500英特尔高清4000英特尔4400显卡740MRadeon HD 631
  • 在 Linux 上运行我自己的程序的权限被拒绝? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有Ubuntu 9 4 我已经构建了程序 一些基本的 OpenGL 该程序只是制作一个旋转的正方形 然后运行它并 sh blabla p
  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染
  • Glew+GLFW Win32 无依赖项 Visual Studio

    是否可以在不将文件复制到 C 的情况下构建并链接 Glew 和 GLFW 我找不到任何说明如何在不将 DLL 复制到 C 上的 Visual Studio 目录的情况下使用这些库的文档 我只想包含项目目录中所需的所有 dll 和 lib 文
  • 立体太阳图 matplotlib 极坐标图 python

    我正在尝试创建一个与以下类似的简单的立体太阳路径图 http wiki naturalfrequent com wiki Sun Path Diagram http wiki naturalfrequency com wiki Sun Pa
  • 根据 GLSL 中向量的特定分量执行最小-最大的最快方法?

    我需要在我的 GLSL 代码中多次调用这种函数 vec2 minx vec2 a vec2 b if a x lt b x return a else return b 我担心过度分支 有没有办法避免 if else 结构 我建议使用 GL

随机推荐

  • pip install pygame - 找不到 SDL.h 文件

    macOS 塞拉利昂 fun python pip version pip 9 0 1 from Library Frameworks Python framework Versions 3 5 lib python3 5 site pac
  • 正则表达式中对 \K 的支持

    The K转义序列将匹配的开头重置为当前位置 令牌列表 这只影响报告为完全匹配的内容 支持哪些环境 语言 版本 K 保留 在其正则表达式引擎中 以及需要哪些库 如果有 才能在模式中使用此功能 The K多种引擎 语言或工具支持转义序列 例如
  • XSL:`xsl:template` 的 `match="/"` 的含义

    我刚刚学习 XML 以及如何使用 XSL 文件 在 XSL 文件中我发现了以下术语 xsl template match 这代表什么 我可以用什么来代替 我可以写吗table或任何其他 HTML 标签来代替 的价值match的属性
  • 什么情况下HTTP_REFERER会为空

    我知道有可能得到一个空的 HTTP REFERER 什么情况下会出现这种情况 如果我得到一个空的 是否总是意味着用户更改了它 获取空值与获取空值相同吗 在什么情况下我也会得到这个 当最终用户 在浏览器地址栏中输入站点 URL 通过浏览器维护
  • 在 C# 中序列化数组列表

    我有一个包含许多标准字段和一个数组列表的类 有没有办法使用 XmlSerializer 序列化该类 到目前为止的尝试会导致一条错误消息 Unhandled Exception System InvalidOperationException
  • 使用 .NET 反应式扩展定期调度 IEnumerable

    比如说我有一个可枚举的 dim e Enumerable Range 0 1024 我希望能够做到 dim o e ToObservable Timespan FromSeconds 1 这样可观察对象每秒都会生成值 直到枚举完毕 我想不出
  • PostgreSQL 中使用“类似”的查询性能

    我需要根据特定列中的某些值从表中检索某些行 名为columnX在示例中 select from tableName where columnX similar to A B C 1 2 3 So if columnX至少包含指定值之一 A
  • 可执行路径指向错误的位置,如何更新

    我最近使用 npm 更新了一个 nodejs 可执行文件 现在该可执行文件指向错误的位置 当我在终端中运行which命令时 它指向旧的不存在的位置 如何更新可执行路径或快捷方式 我不是一个 Unix 人 所以不确定它在哪里设置 我不一定需要
  • 在管理员接受其域的应用程序市场范围后,我们是否需要等待以避免同意屏幕?

    我们正在将我们的应用程序集成到新的 Google Marketplace 中 我们在开发者控制台中的市场配置没问题 我们的 oauth2 sso 流程正常 范围与控制台中的设置匹配 身份验证参数正常 所有用户在通过导航栏访问我们的应用程序时
  • 泛型方法中的原始类型转换,无需装箱

    在对我们的一个应用程序进行一些分析时 我发现了以下代码 public TOut GetValue
  • Kotlin readLine() 函数无法正常工作

    我最近在kotlin中做了一个简单的用户输入代码 我尝试在intellij Idea上运行它 但是它不能正常工作 当我运行代码时 出现 输入文本 部分 我可以输入一些单词 但是readLine 似乎不起作用 因为它没有继续到最后一个 pri
  • 为什么数据库查询在应用程序中只会变慢?

    我有一个网页 需要 10 分钟才能对数据库运行一个查询 但从 SQL Server Management Studio 运行时 相同的查询会在不到一秒的时间内返回 该网页只是向正在执行存储过程的数据库触发 SQL 而数据库又对四个表执行非常
  • 在 C++ 中创建数组而不提前知道长度

    我正在开发一个小程序 以帮助加快我的实验室工作的一些数据分析速度 它应该从文本文件中读取数据 创建一堆包含这些数据的数组 然后进行一些数学运算 我一直遇到的问题是我不知道原始文本文件有多少行 所以我不知道要制作多大的数组 我对 C 很陌生
  • 如何调整背景图像大小以适应Android中的应用程序屏幕尺寸

    我使用的是 s4 Galaxy 我下载了以下壁纸壁纸 http www sswallpaper com get samsung galaxy s4 wallpapers Keep Running 1080x1920 595 2 jpg我尝试
  • 矢量迭代器擦除给我一个运行时错误?

    所以我在我的类中有一个方法 这个类应该做的是 检查 h 文件中的向量是否具有介于double low double high然后删除它们 最后返回删除了多少 空格 所以我尝试了一些方法 但总是遇到运行时错误 它似乎在 for 循环中 但我不
  • 刷新 Excel VBA 函数结果

    如何让用户定义的函数根据电子表格中更改的数据重新评估自身 I tried F9 and Shift F9 似乎唯一有效的方法是使用函数调用编辑单元格 然后按 Enter 键 你应该使用Application Volatile在你的函数的顶部
  • Android 个性化锁屏

    您好 我正在寻找适用于 Android 手机的个性化屏幕储物柜 用户可以以特定模式弯曲手指并解锁屏幕 而不是输入数字 任何指示 想法表示赞赏 您可能想查看 Android 源代码 LockPatternUtils java and 锁屏 j
  • 如何从存储在sd卡上的图像获取图像路径

    是否可以获取 Android 手机 SD 卡上存储的所有图像的路径 还可以检查 SD 卡或内存中存储的其他图像吗 我目前正在这样做 Cursor cur this getContentResolver query MediaStore Im
  • 操作码和操作数的组合无效[重复]

    这个问题在这里已经有答案了 SEGMENT data print db d d d d This is a test of printf 10 0 rowm dw 160 row multiplier iterations db 80 nu
  • GPU 射线投射(单通道),具有球坐标中的 3D 纹理

    我正在实现一种体积渲染算法 GPU 光线投射单通道 为此 我使用强度值的浮点数组作为 3d 纹理 此 3d 纹理描述了球坐标中的常规 3d 网格 这里有数组值的示例 75 839354473071637 64 083049468866022