我一直在尝试使用38leinaD code显示图像。
这是一个略微修改的版本,我尝试显示图像:
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.*;
public class DistortionCorrection {
public enum Eye {
Left, Right
};
protected int shader=0;
protected int vertShader=0;
protected int fragShader=0;
protected int colorTextureID;
protected int framebufferID;
protected int depthRenderBufferID;
private int LensCenterLocation;
private int ScreenCenterLocation;
private int ScaleLocation;
private int ScaleInLocation;
private int HmdWarpParamLocation;
// renderDistortedEye
public static float K0 = 1.0f;
public static float K1 = 0.22f;
public static float K2 = 0.24f;
public static float K3 = 0.0f;
// Added
BufferedImage panda;
private static final int BYTES_PER_PIXEL = 4;
int pandaID;
private final static String VERTEX_SHADER_SOURCE =
"void main() {\n" +
" gl_TexCoord[0] = gl_MultiTexCoord0;\n" +
" gl_Position = gl_Vertex;\n" +
"}";
private final static String FRAGMENT_SHADER_SOURCE =
"uniform sampler2D tex;\n" +
"uniform vec2 LensCenter;\n" +
"uniform vec2 ScreenCenter;\n" +
"uniform vec2 Scale;\n" +
"uniform vec2 ScaleIn;\n" +
"uniform vec4 HmdWarpParam;\n" +
"\n" +
"vec2 HmdWarp(vec2 texIn)\n" +
"{\n" +
" vec2 theta = (texIn - LensCenter) * ScaleIn;\n" +
" float rSq= theta.x * theta.x + theta.y * theta.y;\n" +
" vec2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + " +
" HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n" +
" return LensCenter + Scale * theta1;\n" +
"}\n" +
"\n" +
"\n" +
"\n" +
"void main()\n" +
"{\n" +
" vec2 tc = HmdWarp(gl_TexCoord[0].xy);\n" +
" if (any(notEqual(clamp(tc, ScreenCenter-vec2(0.25,0.5), ScreenCenter+vec2(0.25, 0.5)) - tc, vec2(0.0, 0.0))))\n" +
" gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n" +
" else\n" +
" gl_FragColor = texture2D(tex, tc);\n" +
"}";
public DistortionCorrection(int screenWidth, int screenHeight) {
initShaders(VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);
initFBO(screenWidth, screenHeight);
// Added
glOrtho(0, Display.getWidth(), Display.getHeight(), 0, -1, 1);
try {
panda = ImageIO.read(new File("/Users/webstorms/Desktop/panda.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
glEnable(GL_TEXTURE_2D);
pandaID = loadTexture(panda);
glBindTexture(GL_TEXTURE_2D, pandaID);
// Added end
Util.checkGLError();
LensCenterLocation = glGetUniformLocation(shader, "LensCenter");
ScreenCenterLocation = glGetUniformLocation(shader, "ScreenCenter");
ScaleLocation = glGetUniformLocation(shader, "Scale");
ScaleInLocation = glGetUniformLocation(shader, "ScaleIn");
HmdWarpParamLocation = glGetUniformLocation(shader, "HmdWarpParam");
System.out.println(FRAGMENT_SHADER_SOURCE);
Util.checkGLError();
}
private void initFBO(int screenWidth, int screenHeight) {
framebufferID = glGenFramebuffers();
colorTextureID = glGenTextures();
depthRenderBufferID = glGenRenderbuffers();
glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
// initialize color texture
glBindTexture(GL_TEXTURE_2D, colorTextureID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screenWidth, screenHeight, 0,GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, colorTextureID, 0);
// initialize depth renderbuffer
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBufferID);
glRenderbufferStorage(GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, depthRenderBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
public void beginOffScreenRenderPass() {
glBindTexture(GL_TEXTURE_2D, 0);
Util.checkGLError();
glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
Util.checkGLError();
}
public void endOffScreenRenderPass() {
}
public void renderToScreen() {
Util.checkGLError();
glUseProgram(shader);
Util.checkGLError();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor (1.0f, 0.0f, 0.0f, 0.5f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, colorTextureID);
renderDistortedEye(Eye.Left, 0.0f, 0.0f, 0.5f, 1.0f);
renderDistortedEye(Eye.Right, 0.5f, 0.0f, 0.5f, 1.0f);
glUseProgram(0);
glEnable(GL_DEPTH_TEST);
}
public void renderDistortedEye(Eye eye, float x, float y, float w, float h) {
float as = w/h;
float scaleFactor = 1.0f;
Util.checkGLError();
float DistortionXCenterOffset;
if (eye == Eye.Left) {
DistortionXCenterOffset = 0.25f;
}
else {
DistortionXCenterOffset = -0.25f;
}
glUniform2f(LensCenterLocation, x + (w + DistortionXCenterOffset * 0.5f)*0.5f, y + h*0.5f);
glUniform2f(ScreenCenterLocation, x + w*0.5f, y + h*0.5f);
glUniform2f(ScaleLocation, (w/2.0f) * scaleFactor, (h/2.0f) * scaleFactor * as);;
glUniform2f(ScaleInLocation, (2.0f/w), (2.0f/h) / as);
glUniform4f(HmdWarpParamLocation, K0, K1, K2, K3);
if (eye == Eye.Left) {
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
glTexCoord2f(0.5f, 0.0f); glVertex2f(0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
glTexCoord2f(0.5f, 1.0f); glVertex2f(0.0f, 1.0f);
glEnd();
}
else {
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.5f, 0.0f); glVertex2f(0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f);
glTexCoord2f(0.5f, 1.0f); glVertex2f(0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
glEnd();
}
}
protected void initShaders(String vertexShader, String fragmentShader) {
shader=glCreateProgram();
vertShader=createVertShader(vertexShader);
fragShader=createFragShader(fragmentShader);
glAttachShader(shader, vertShader);
glAttachShader(shader, fragShader);
glLinkProgram(shader);
glValidateProgram(shader);
}
private int createVertShader(String vertexCode){
vertShader=glCreateShader(GL_VERTEX_SHADER);
if (vertShader==0) {
return 0;
}
glShaderSource(vertShader, vertexCode);
glCompileShader(vertShader);
return vertShader;
}
private int createFragShader(String fragCode){
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
if (fragShader==0) {
return 0;
}
glShaderSource(fragShader, fragCode);
glCompileShader(fragShader);
return fragShader;
}
public static void main(String[] args) {
try {
DisplayMode displayMode = Display.getDesktopDisplayMode();
Display.setDisplayMode(displayMode);
Display.setTitle("Barrel Distorion Shader");
Display.setFullscreen(true);
PixelFormat pixelFormat = new PixelFormat(8, 8, 8);
Display.create(pixelFormat);
} catch (LWJGLException e) {
e.printStackTrace();
}
DistortionCorrection shader = new DistortionCorrection(640, 400);
while (!Display.isCloseRequested()) {
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
System.exit(0);
}
shader.beginOffScreenRenderPass();
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Content
// Added
// glPushMatrix();
// glTranslatef(100, 100, 0);
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(Display.getWidth(), 0);
glTexCoord2f(1, 1);
glVertex2f(Display.getWidth(), Display.getHeight());
glTexCoord2f(0, 1);
glVertex2f(0, Display.getHeight());
}
glEnd();
// glPopMatrix();
// Added end
/*
glBegin(GL_LINES);
glColor3f(1.0f, 1.0f, 0.0f);
for (int i=0; i<20; i++) {
glVertex2f(-1.0f, -1.0f + 0.1f * i);
glVertex2f(1.0f, -1.0f + 0.1f * i);
}
for (int i=0; i<20; i++) {
glVertex2f(-1.0f + 0.1f * i, -1.0f);
glVertex2f(-1.0f + 0.1f * i, 1.0f);
}
glEnd(); */
shader.endOffScreenRenderPass();
shader.renderToScreen();
Display.sync(60);
Display.update();
}
}
public static int loadTexture(BufferedImage image){
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component
buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component
buffer.put((byte) (pixel & 0xFF)); // Blue component
buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA
}
}
buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS
// You now have a ByteBuffer filled with the color data of each pixel.
// Now just create a texture ID and bind it. Then you can load it using
// whatever OpenGL method you want, for example:
int textureID = glGenTextures(); //Generate texture ID
glBindTexture(GL_TEXTURE_2D, textureID); //Bind texture ID
//Setup wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
//Setup texture scaling filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Send texel data to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
//Return the texture ID so we can bind it later again
return textureID;
}
}
答案 0 :(得分:0)
根据您的意见,我对您的代码进行了一些可能实现您想要的更改:
//
// This polygon is wound Clockwise instead of Counter-Clockwise; when you start
// using projection matrices and face culling this is a concept you will need
// to understand.
//
// Counter-Clockwise is the preferred winding order in OpenGL, by the way - I
// just wanted to show this to you for future reference.
//
glBegin (GL_QUADS);
{
glTexCoord2f ( 0.0f, 0.0f);
glVertex2f (-1.0f, -1.0f); // Bottom-left
glTexCoord2f ( 0.0f, 1.0f);
glVertex2f (-1.0f, 1.0f); // Top-Left
glTexCoord2f ( 1.0f, 1.0f);
glVertex2f ( 1.0f, 1.0f); // Top-Right
glTexCoord2f ( 1.0f, 0.0f);
glVertex2f ( 1.0f, -1.0f); // Bottom-Right
}
glEnd ();
此代码使用规范化设备坐标,这样您就不必知道窗口的尺寸,以便创建填充整个屏幕的四边形(更重要的是不需要非标识投影矩阵) 子>
我不知道这是否会解决你的整个问题,但这绝对是一个开始。