当前位置: 首页 > 知识库问答 >
问题:

在LWJGL3中使用HDR地图

苍嘉澍
2023-03-14

我目前正在使用LWJGL3并构建一个简单的Skybox。我想让skybox接收一个HDR文件,一个等长方形的地图。我可以得到一个skybox运行与PNG与PNG解码器,但不确定它将如何与HDR文件。据我所知,STB(在C++中)允许在程序中上传HDR文件,LWJGL3也支持STB。

我如何创建一个支持机顶盒和HDR文件的loadTexture函数?

编辑:我要把我的进展发布给任何人,这样任何人都可以看到我一直在做什么。

public int loadCubeMap(String textureFile) throws IOException {

 int texID = glGenTextures();
 glBindTexture(GL_TEXTURE_2D, texID);

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

 ByteBuffer imageBuffer;
 IntBuffer w = BufferUtils.createIntBuffer(1);
 IntBuffer h = BufferUtils.createIntBuffer(1);
 IntBuffer comp = BufferUtils.createIntBuffer(1);
 ByteBuffer image;

 imageBuffer = IOUtil.ioResourceToByteBuffer(textureFile, 8 * 1024);

 if (!stbi_info_from_memory(imageBuffer, w, h, comp))
     throw new IOException("Failed to read image information: " + stbi_failure_reason());

 image = stbi_load_from_memory(imageBuffer, w, h, comp, 3);

 if (image == null)
     throw new IOException("Failed to load image: " + stbi_failure_reason());
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w.get(0), h.get(0), 0, GL_RGB, GL_UNSIGNED_BYTE, image);

 stbi_image_free(image);

 return texID; }
private static final float SIZE = 500f;

private static final float[] VERTICES = {        
    -SIZE,  SIZE, -SIZE,
    -SIZE, -SIZE, -SIZE,
    SIZE, -SIZE, -SIZE,
     SIZE, -SIZE, -SIZE,
     SIZE,  SIZE, -SIZE,
    -SIZE,  SIZE, -SIZE,

    -SIZE, -SIZE,  SIZE,
    -SIZE, -SIZE, -SIZE,
    -SIZE,  SIZE, -SIZE,
    -SIZE,  SIZE, -SIZE,
    -SIZE,  SIZE,  SIZE,
    -SIZE, -SIZE,  SIZE,

     SIZE, -SIZE, -SIZE,
     SIZE, -SIZE,  SIZE,
     SIZE,  SIZE,  SIZE,
     SIZE,  SIZE,  SIZE,
     SIZE,  SIZE, -SIZE,
     SIZE, -SIZE, -SIZE,

    -SIZE, -SIZE,  SIZE,
    -SIZE,  SIZE,  SIZE,
     SIZE,  SIZE,  SIZE,
     SIZE,  SIZE,  SIZE,
     SIZE, -SIZE,  SIZE,
    -SIZE, -SIZE,  SIZE,

    -SIZE,  SIZE, -SIZE,
     SIZE,  SIZE, -SIZE,
     SIZE,  SIZE,  SIZE,
     SIZE,  SIZE,  SIZE,
    -SIZE,  SIZE,  SIZE,
    -SIZE,  SIZE, -SIZE,

    -SIZE, -SIZE, -SIZE,
    -SIZE, -SIZE,  SIZE,
     SIZE, -SIZE, -SIZE,
     SIZE, -SIZE, -SIZE,
    -SIZE, -SIZE,  SIZE,
     SIZE, -SIZE,  SIZE
};

private RawModel cube;
private int skyboxTexture;
private SkyboxShader shader;

public SkyboxRenderer(Loader loader, Matrix4f projectionMatrix) throws IOException {
    cube = loader.loadToVAO(VERTICES, 3);
    skyboxTexture = loader.loadCubeMap("res/newport_loft.hdr");
    shader = new SkyboxShader();
    shader.start();
    shader.loadProjectionMatrix(projectionMatrix);
    shader.connectTextureUnits();
    shader.stop();
    }

public void render(Camera camera) {
    shader.start();
    shader.loadViewMatrix(camera);
    GL30.glBindVertexArray(cube.getVaoID());
    GL20.glEnableVertexAttribArray(0);

    GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, skyboxTexture);
    GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
    shader.stop();
    }
}
#version 330 core 

layout (location = 0) in vec3 aPos;

out vec3 WorldPos;

uniform mat4 projection; 
uniform mat4 view;

void main() {
    WorldPos = aPos;  
    gl_Position =  projection * view * vec4(WorldPos, 1.0); }
#version 330 core
out vec4 FragColor;
in vec3 WorldPos;

uniform sampler2D equirectangularMap;

const vec2 invAtan = vec2(0.1591, 0.3183);
vec2 SampleSphericalMap(vec3 v)
{
    vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
    uv *= invAtan;
    uv += 0.5;
    return uv;
}

void main()
{       
    vec2 uv = SampleSphericalMap(normalize(WorldPos));
    vec3 color = texture(equirectangularMap, uv).rgb;

    FragColor = vec4(color, 1.0);
}

着色器代码在ThinMatrix教程的帮助下工作得很好。

公共类SkyboxShader扩展ShaderProgram{

private static final String VERTEX_FILE = "src/skybox/cubemap.vs";
private static final String FRAGMENT_FILE = "src/skybox/cubemap.fs";

private int location_projectionMatrix;
private int location_viewMatrix;

private int location_equirectangularMap;

public SkyboxShader() {
    super(VERTEX_FILE, FRAGMENT_FILE);
}

public void loadProjectionMatrix(Matrix4f matrix){
    super.loadMatrix(location_projectionMatrix, matrix);
}

public void loadViewMatrix(Camera camera){
    Matrix4f matrix = Maths.createViewMatrix(camera);
    super.loadMatrix(location_viewMatrix, matrix);
}

@Override
protected void getAllUniformLocations() {
    location_projectionMatrix = super.getUniformLocation("projection");
    location_viewMatrix = super.getUniformLocation("view");
    location_equirectangularMap = super.getUniformLocation("equirectangularMap");
}

@Override
protected void bindAttributes() {
    super.bindAttribute(0, "aPos");
}

public void connectTextureUnits() {
    super.loadInt(location_equirectangularMap, 0);
} }

我在skybox渲染器中初始化loadCubeMap函数以及文件名,然后在主渲染器类中初始化skybox渲染器。

编辑:

所以我试着重新设计它。image变量被更改为浮动缓冲区,现在接受带有stbi_loadf_from_memory的image。还是一个但是很困惑,没想到HDR地图会这么困惑。

public int loadCubeMap(String textureFile) throws IOException {

         int texID = glGenTextures();
         //glActiveTexture(GL11.GL_TEXTURE);
         glBindTexture(GL_TEXTURE_2D, texID);

         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

         ByteBuffer imageBuffer;
         IntBuffer w = BufferUtils.createIntBuffer(1);
         IntBuffer h = BufferUtils.createIntBuffer(1);
         IntBuffer comp = BufferUtils.createIntBuffer(1);
         FloatBuffer image;

         imageBuffer = IOUtil.ioResourceToByteBuffer(textureFile, 8 * 1024);

         if (!stbi_info_from_memory(imageBuffer, w, h, comp))
             throw new IOException("Failed to read image information: " + stbi_failure_reason());

         image = stbi_loadf_from_memory(imageBuffer, w, h, comp, 3);



         if (image == null)
             throw new IOException("Failed to load image: " + stbi_failure_reason());
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, w.get(0), h.get(0), 0, GL_RGB16, GL_FLOAT, image);

         stbi_image_free(image);

         return texID;

共有1个答案

贺跃
2023-03-14

应该使用stbi_load_from_memory(),而不是stbi_loadf_from_memory(),这是读取HDR文件的函数。STB还包含stbi_is_hdr_from_memory()等函数,这些函数允许您确保缓冲区包含HDR映像。

注意stbi_load_from_memory()返回一个包含纹理的floatbuffer

此外,您应该修改对glteximage2d()的调用:

    null
 类似资料:
  • LWJGL - Lightweight Java Game Library 3 LWJGL (https://www.lwjgl.org) is a Java library that enables cross-platformaccess to popular native APIs useful in the development of graphics(OpenGL/Vulkan), a

  • lwjgl.org - Home of Lightweight Java Game Library The website for LWJGL is build with React. It is a single-page application with client-side routing. It installs a Service Worker in order to work off

  • HDR

    Note 本节暂未进行完全的重写,错误可能会很多。如果可能的话,请对照原文进行阅读。如果有报告本节的错误,将会延迟至重写之后进行处理。 一般来说,当存储在帧缓冲(Framebuffer)中时,亮度和颜色的值是默认被限制在0.0到1.0之间的。这个看起来无辜的语句使我们一直将亮度与颜色的值设置在这个范围内,尝试着与场景契合。这样是能够运行的,也能给出还不错的效果。但是如果我们遇上了一个特定的区域,其

  • Luminance HDR (Qtpfsgui) 是一个对数码相片进行各种效果调整的工具。

  • 我正在学习一个关于在屏幕上渲染文本的教程,但我似乎找不到加载字体纹理的有效方法。我尝试了slick库,但它已经过时了:它使用lwjgl2的方法,lwjgl3中不再存在,因此它抛出了一个java。lang.NoSuchMethodError。在互联网上,我发现glfw(集成在lwjgl中)有一种称为glfwLoadTexture2D的方法,但它似乎只在glfw的C版本中可用。我还在openGL UT

  • 我正在尝试在使用SceneKit的Swift项目中使用球形HDR图像作为环境灯,并且在使用标准32bpc HDR成像格式时遇到困难。我可以轻松使用PNG地图,但无法从OpenEXR. exr或Radiance. hdr文件加载图像。 在这个文档页面中,它似乎描述了我所追求的功能。 我找不到任何apple文档来描述它,因此我目前的最佳猜测是编写自己的函数来加载文件,然后使用自定义CGDataProv