Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用skybox程序生成恒星_C++_Opengl_Procedural Generation - Fatal编程技术网

C++ 用skybox程序生成恒星

C++ 用skybox程序生成恒星,c++,opengl,procedural-generation,C++,Opengl,Procedural Generation,我正试图在OpenGL中按程序生成一个充满星星的背景 我正在采取的方法是创建一个具有立方体贴图纹理的skybox。立方体贴图纹理的每一侧基本上由2048x2048黑色图像组成,随机选择的纹理元素设置为白色。结果如下: 我不确定从图像上看它有多明显,但当移动时,随着靠近盒子边缘的恒星看起来越来越小,可以看到一个非常独特的盒子形状。我怎样才能防止这种情况?我是否需要放弃skybox方法,转而使用类似skysphere的东西 编辑:下面是我如何将立方体贴图映射到天空的 // Create and bi

我正试图在OpenGL中按程序生成一个充满星星的背景

我正在采取的方法是创建一个具有立方体贴图纹理的skybox。立方体贴图纹理的每一侧基本上由2048x2048黑色图像组成,随机选择的纹理元素设置为白色。结果如下:

我不确定从图像上看它有多明显,但当移动时,随着靠近盒子边缘的恒星看起来越来越小,可以看到一个非常独特的盒子形状。我怎样才能防止这种情况?我是否需要放弃skybox方法,转而使用类似skysphere的东西

编辑:下面是我如何将立方体贴图映射到天空的

// Create and bind texture.
glGenTextures(1, &texture_);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, texture_);

for (unsigned int i = 0; i < 6; ++i) {
    std::vector<std::uint8_t> image = generateTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT,
                 0, GL_RGB, GL_UNSIGNED_BYTE, image.data());
}

// Set texture parameters.
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
EDIT2:这是用于渲染天空的绘制函数

void Stars::draw(const Camera& camera) const {
    // Skybox will be rendered last. In order to ensure that the stars are rendered at the back of
    // the scene, the depth buffer is filled with values of 1.0 for the skybox -- this is done in
    // the vertex shader. We need to make sure that the skybox passes the depth te3t with values
    // less that or equal to the depth buffer.
    glDepthFunc(GL_LEQUAL);

    program_.enable();

    // Calculate view-projection matrix and set the corresponding uniform. The view matrix must be
    // stripped of translation components so that the skybox follows the camera.
    glm::mat4 view       = glm::mat4(glm::mat3(camera.viewMatrix()));
    glm::mat4 projection = camera.projectionMatrix();

    glm::mat4 VP = projection * view;
    glUniformMatrix4fv(program_.uniformLocation("VP"), 1, GL_FALSE, glm::value_ptr(VP));

    // Bind buffer objects and texture to current context and draw.
    glBindVertexArray(vao_);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_);

    glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(INDICES.size()), GL_UNSIGNED_INT,
                   reinterpret_cast<GLvoid *>(0));

    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    program_.disable();

    glDepthFunc(GL_LESS);
}
void Stars::draw(常量摄影机和摄影机)常量{
//Skybox将最后渲染。为了确保星星渲染在
//在场景中,skybox的深度缓冲区填充了1.0的值——这是在中完成的
//顶点着色器。我们需要确保skybox通过深度te3t,并带有值
//小于或等于深度缓冲区。
glDepthFunc(GL_LEQUAL);
程序启用();
//计算视图投影矩阵并设置相应的一致性。视图矩阵必须为
//去除平移组件,使skybox跟随摄影机。
glm::mat4视图=glm::mat4(glm::mat3(camera.viewMatrix());
glm::mat4 projection=camera.projectionMatrix();
glm::mat4 VP=投影*视图;
glUniformMatrix4fv(程序统一位置(“VP”),1,GL_FALSE,glm::value_ptr(VP));
//将缓冲区对象和纹理绑定到当前上下文并绘制。
glBindVertexArray(vao_);
glBindBuffer(GL_元素_数组_缓冲区,ebo_);
glBindTexture(GL_纹理_立方体_贴图,纹理_);
GLD元素(GLU三角形、静态类型转换(index.size())、GLU无符号整数、,
重新解释(0);
glBindVertexArray(0);
glBindBuffer(GL_元素_数组_缓冲区,0);
glBindTexture(GL_纹理_立方体_贴图,0);
程序禁用();
glDepthFunc(GL_LESS);
}
  • 以一定的立方体积均匀地生成恒星

    x=2.0*Random()-1.0; // <-1,+1>
    y=2.0*Random()-1.0; // <-1,+1>
    z=2.0*Random()-1.0; // <-1,+1>
    
    看起来它应该在这里预览(混合球体/立方体贴图):

    虽然看起来有孔,但没有(可能是某些混合错误),如果禁用球体贴图渲染,则贴图中没有可见的孔或扭曲

    用于测试的球体三角剖分
    网格obj
    取自此处:

    [Edit1]是的,有一个愚蠢的混合错误

    我修复了代码。。。但问题依然存在。不要紧,此映射正在工作,更新的代码结果如下:

    因此,只需将代码调整到您的纹理生成器

    [Edit2]随机星

    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    int i;
    float x,y,z,d;
    RandSeed=8123456789;
    
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE);
    
    glPointSize(2.0);
    glBegin(GL_POINTS);
    for (i=0;i<1000;i++)
        {
        // uniform random cartesian stars inside cube
        x=(2.0*Random())-1.0;
        y=(2.0*Random())-1.0;
        z=(2.0*Random())-1.0;
        // project on unit sphere
        d=sqrt((x*x)+(y*y)+(z*z));
        if (d<1e-3) { i--; continue; }
        d=1.0/d;
        x*=d; y*=d; z*=d;
        // redish sphere map
        glColor3f(0.6,0.3,0.0); glVertex3f(x,y,z);
        // cube half size=1 undistort using similarities like: y/x = y'/x'
             if ((fabs(x)>=fabs(y))&&(fabs(x)>=fabs(z))){ y/=x; z/=x; if (x>=0) x=1.0; else x=-1.0; }
        else if ((fabs(y)>=fabs(x))&&(fabs(y)>=fabs(z))){ x/=y; z/=y; if (y>=0) y=1.0; else y=-1.0; }
        else if ((fabs(z)>=fabs(x))&&(fabs(z)>=fabs(y))){ x/=z; y/=z; if (z>=0) z=1.0; else z=-1.0; }
        // bluish cube map
        glColor3f(0.0,0.3,0.6); glVertex3f(x,y,z);
        }
    glEnd();
    glPointSize(1.0);
    glDisable(GL_BLEND);
    glFlush();
    SwapBuffers(hdc);
    
    在这里,混合的结果是最终的颜色应该是这样的,当从
    (0,0,0)
    观看时,球体和立方体星星完全重叠(白色):


    为什么要贴一个黑色矩形?“这么浪费内存/存储空间。”托马斯马修斯?图像中应该有星星。不清楚你是如何将立方体映射到你的天空的。请提供一个示例。在立方体面上生成星星可能看起来是均匀分布的,但一旦添加透视变换,立方体的形状将是显而易见的,正如您所看到的。你需要做一些更复杂的事情,把它们映射到你的立方体上。要让立方体上的纹理看起来均匀是非常困难的。一般来说,你可以做三件事中的一件。1) 使立方体更为矩形(在Y向上世界的XZ平面中),以便天空更近,角点不那么明显(假设场景中有对象)。2) 使用球坐标在随机方向投射光线,并按恒星的反距离缩放恒星的大小。3) 我建议使用球形贴图而不是立方体贴图。这种方法不会导致极点周围的更高密度吗?呼应@Rhymoid注释,使用球坐标的随机分布将导致恒星的不均匀分布。如果你修改你答案的那一部分,我会接受的。这表明它只需在
    [-1,+1]
    中生成三个均匀的随机值,并将这些点投影到单位球体上即可。这可能不是最快的方法,但它确实很简单。@Rhymoid heh刚刚实现了相同的独立性。现在,比较使它比其他方法更难理解。
        glClearColor(0.0,0.0,0.0,0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        int i,n=10000;
        float a,b,x,y,z;
        //RandSeed=8123456789;
        n=obj.pnt.num;  // triangulated sphere point list
    
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE,GL_ONE);
    
        glPointSize(2.0);
        glBegin(GL_POINTS);
        for (i=0;i<n;i++)
            {
            // equidistant points instead of random to test this
            x=obj.pnt[i].p[0];
            y=obj.pnt[i].p[1];
            z=obj.pnt[i].p[2];
    /*
            // random star spherical position
            a=2.0*M_PI*Random();
            b=M_PI*(Random()-0.5);
            // spherical 2 cartessian r=1;
            x=cos(a)*cos(b);
            y=sin(a)*cos(b);
            z=       sin(b);
    */
            // redish sphere map
            glColor3f(0.6,0.3,0.0); glVertex3f(x,y,z);
            // cube half size=1 undistort // using similarities like: yy/xx = y/x
                 if ((fabs(x)>=fabs(y))&&(fabs(x)>=fabs(z))){ y/=x; z/=x; if (x>=0) x=1.0; else x=-1.0; }
            else if ((fabs(y)>=fabs(x))&&(fabs(y)>=fabs(z))){ x/=y; z/=y; if (y>=0) y=1.0; else y=-1.0; }
            else if ((fabs(z)>=fabs(x))&&(fabs(z)>=fabs(y))){ x/=z; y/=z; if (z>=0) z=1.0; else z=-1.0; }
            // bluish cube map
            glColor3f(0.0,0.3,0.6); glVertex3f(x,y,z);
            }
        glEnd();
        glPointSize(1.0);
        glDisable(GL_BLEND);
        glFlush();
        SwapBuffers(hdc);
    
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    int i;
    float x,y,z,d;
    RandSeed=8123456789;
    
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE,GL_ONE);
    
    glPointSize(2.0);
    glBegin(GL_POINTS);
    for (i=0;i<1000;i++)
        {
        // uniform random cartesian stars inside cube
        x=(2.0*Random())-1.0;
        y=(2.0*Random())-1.0;
        z=(2.0*Random())-1.0;
        // project on unit sphere
        d=sqrt((x*x)+(y*y)+(z*z));
        if (d<1e-3) { i--; continue; }
        d=1.0/d;
        x*=d; y*=d; z*=d;
        // redish sphere map
        glColor3f(0.6,0.3,0.0); glVertex3f(x,y,z);
        // cube half size=1 undistort using similarities like: y/x = y'/x'
             if ((fabs(x)>=fabs(y))&&(fabs(x)>=fabs(z))){ y/=x; z/=x; if (x>=0) x=1.0; else x=-1.0; }
        else if ((fabs(y)>=fabs(x))&&(fabs(y)>=fabs(z))){ x/=y; z/=y; if (y>=0) y=1.0; else y=-1.0; }
        else if ((fabs(z)>=fabs(x))&&(fabs(z)>=fabs(y))){ x/=z; y/=z; if (z>=0) z=1.0; else z=-1.0; }
        // bluish cube map
        glColor3f(0.0,0.3,0.6); glVertex3f(x,y,z);
        }
    glEnd();
    glPointSize(1.0);
    glDisable(GL_BLEND);
    glFlush();
    SwapBuffers(hdc);
    
        glClearColor(0.0,0.0,0.0,0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        int i;
        float x,y,z,d;
        RandSeed=8123456789;
    
        glDepthFunc(GL_ALWAYS);
    //  glDepthFunc(GL_LEQUAL);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE,GL_ONE);
    
        glPointSize(2.0);
        glBegin(GL_POINTS);
        for (i=0;i<25000;i++)
            {
            // uniform random cartesian stars inside cube
            x=(2.0*Random())-1.0;
            y=(2.0*Random())-1.0;
            z=(2.0*Random())-1.0;
            // project on unit sphere
            d=sqrt((x*x)+(y*y)+(z*z));
            if (d<1e-3) { i--; continue; }
            d=1.0/d;
            x*=d; y*=d; z*=d;
            // redish sphere map
            glColor3f(0.6,0.3,0.0); glVertex3f(x,y,z);
            // cube half size=1 undistort using similarities like: y/x = y'/x'
                 if ((fabs(x)>=fabs(y))&&(fabs(x)>=fabs(z))){ y/=fabs(x); z/=fabs(x); if (x>=0) x=1.0; else x=-1.0; }
            else if ((fabs(y)>=fabs(x))&&(fabs(y)>=fabs(z))){ x/=fabs(y); z/=fabs(y); if (y>=0) y=1.0; else y=-1.0; }
            else if ((fabs(z)>=fabs(x))&&(fabs(z)>=fabs(y))){ x/=fabs(z); y/=fabs(z); if (z>=0) z=1.0; else z=-1.0; }
            // bluish cube map
            glColor3f(0.0,0.3,0.6); glVertex3f(x,y,z);
            }
        glEnd();
        glPointSize(1.0);
        glDisable(GL_BLEND);
        glFlush();
        SwapBuffers(hdc);