小编Sta*_*tan的帖子

通过计算着色器在OpenGL中进行光线跟踪

我试图通过计算着色器在OpenGL中做一些光线跟踪,我遇到了一个奇怪的问题.目前我只想显示没有任何阴影的球体.我的计算着色器为每个像素启动一条光线,如下所示:

#version 430
struct Sphere{
    vec4    position;
    float   radius;
};

struct Ray{
    vec3    origin;
    vec3    dir;
};

uniform image2D outputTexture;
uniform uint        width;
uniform uint        height;

float hitSphere(Ray r, Sphere s){

    float s_vv = dot(r.dir, r.dir);
    float s_ov = dot(r.origin, r.dir);
    float s_mv = dot(s.position.xyz, r.dir);
    float s_mm = dot(s.position.xyz, s.position.xyz);
    float s_mo = dot(s.position.xyz, r.origin);
    float s_oo = dot(r.origin, r.origin);

    float d = s_ov*s_ov-2*s_ov*s_mv+s_mv*s_mv-s_vv*(s_mm-2*s_mo*s_oo-s.radius*s.radius);

    if(d < 0){
        return -1.0f;
    } else if(d == 0){
        return (s_mv-s_ov)/s_vv;
    } else { …
Run Code Online (Sandbox Code Playgroud)

opengl raytracing gpgpu compute-shader

9
推荐指数
1
解决办法
2868
查看次数

OpenGL Compute Shader Invocations

我得到了一个与新计算着色器相关的问题.我目前正在研究粒子系统.我将所有粒子存储在着色器存储缓冲区中,以便在计算着色器中访问它们.然后我派遣一个一维工作组.

#define WORK_GROUP_SIZE 128
_shaderManager->useProgram("computeProg");
glDispatchCompute((_numParticles/WORK_GROUP_SIZE), 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
Run Code Online (Sandbox Code Playgroud)

我的计算着色器:

#version 430
struct particle{
         vec4 currentPos;
         vec4 oldPos;
};

layout(std430, binding=0) buffer particles{
         struct particle p[];
};

layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
void main(){
         uint gid = gl_GlobalInvocationID.x;

         p[gid].currentPos.x += 100;
}
Run Code Online (Sandbox Code Playgroud)

但不知何故并非所有粒子都受到影响.我这样做就像在这个例子中一样,但它不起作用.http://education.siggraph.org/media/conference/S2012_Materials/ComputeShader_6pp.pdf

编辑:

在我调用glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)后,我继续这样:

_shaderManager->useProgram("shaderProg"); 
glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID); 
glVertexPointer(4,GL_FLOAT,sizeof(glm::vec4), (void*)0);
glEnableClientState(GL_VERTEX_ARRAY); 
glDrawArrays(GL_POINTS, 0, _numParticles); 
glDisableClientState(GL_VERTEX_ARRAY);
Run Code Online (Sandbox Code Playgroud)

那么在这种情况下哪个位适合使用?

c++ opengl gpgpu compute-shader

6
推荐指数
2
解决办法
5175
查看次数

着色器存储缓冲区中的OpenGL顶点

我现在正在使用计算着色器处理粒子系统.我将所有粒子都放在着色器存储缓冲区中.粒子包含两个顶点,即当前位置和前一个位置.

struct Particle{
    glm::vec4   _currPosition;
    glm::vec4   _prevPosition;
};
Run Code Online (Sandbox Code Playgroud)

在我调度计算着色器之后,我想直接从着色器存储缓冲区中绘制所有粒子.所以这就是我做的:

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBufferID);
_shaderManager->useProgram("computeProg");
glDispatchCompute((_numParticles/WORK_GROUP_SIZE)+1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
_shaderManager->useProgram("shaderProg");
glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBufferID);
glVertexPointer(4,GL_FLOAT, sizeof(glm::vec4), (GLvoid*)0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, _numParticles);
glDisableClientState(GL_VERTEX_ARRAY);
Run Code Online (Sandbox Code Playgroud)

问题是我在屏幕上看到了_numParticles,但是一半是用我的粒子结构的_prevPosition属性渲染的.这意味着一个粒子被解释为在屏幕上绘制的两个顶点.但我希望他跳过每个粒子结构中的_prevPosition属性.哪里是我的错?

也许我初始化着色器存储缓冲区的方式很重要:

GLuint shaderStorageBufferID;

glGenBuffers(1, &shaderStorageBufferID);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBufferID);
glBufferData(GL_SHADER_STORAGE_BUFFER, numParticles*sizeof(Particle), NULL ,GL_STATIC_DRAW);
struct Particle* particles = (struct Particle*) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, numParticles*sizeof(Particle), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
for(int i = 0; i < numParticles; ++i){
    particles[i]._currPosition = glm::vec4(i, 0, 0.0, 1.0f);
    particles[i]._prevPosition = glm::vec4(i, 0, 1.0, 1.0f);
}
Run Code Online (Sandbox Code Playgroud)

c++ opengl

5
推荐指数
1
解决办法
2674
查看次数

仅在 Manager 类中创建对象

我想创建一个管理器类来管理一种类型的所有创建的对象。当然,这个类也应该创建这些对象。因此,客户端不允许自己创建对象,而必须始终使用管理器类来创建对象。此外,客户可以定义自己的类,这些类将由一名经理管理。

template<class Type>
class Manager{
  //...
  Type* createInstance(){
    Type* ptr = new Type();
    //do sommething
    return ptr;
  }
};
Run Code Online (Sandbox Code Playgroud)

问题是:如何将实例的创建仅限于管理器类?

一种可能是将构造函数声明为私有,并将 Manager 类声明为友元类:

class A{
  friend class Manager<A>;
private:
  A(){}
  ~A(){}   
};
Run Code Online (Sandbox Code Playgroud)

由于允许客户定义自己的类,他只需将构造函数声明为公共,并且管理器仍然可以正常工作。但是客户端将能够在没有管理器类见证的情况下创建这些类的实例,从而导致框架的不良行为/资源管理。

有办法解决这个问题吗?

c++ templates design-patterns

5
推荐指数
1
解决办法
1893
查看次数