📄 bloomopengl.java
字号:
/*
* Copyright (c) 2007, Romain Guy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the TimingFramework project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import com.sun.opengl.util.BufferUtil;
import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;
/**
* THIS DEMO REQUIRES THE JOGL LIBRARY TO COMPILE AND EXECUTE !
*
* JOGL can be found at http://jogl.dev.java.net for your OS.
*
* /!\ The rendering happens in FBOs so that you can get the result back into
* a Java 2D image without displaying it on screen through a GLJPanel. This
* implementation does not offer the conversion from FBO to a BufferedImage
* but you can do it by reading the texture data from frameBufferTexture2.
*
* @author Romain Guy <romain.guy@mac.com>
*/
public class BloomOpenGL extends GLJPanel implements GLEventListener {
private int frameBufferObject1 = -1;
private int frameBufferTexture1 = -1;
private int frameBufferObject2 = -1;
private int frameBufferTexture2 = -1;
private Texture texture;
private BufferedImage image;
private GLU glu = new GLU();
private String blurShaderSource =
"const int MAX_KERNEL_SIZE = 25;" +
"uniform sampler2D baseImage;" +
"uniform vec2 offsets[MAX_KERNEL_SIZE];" +
"uniform float kernelVals[MAX_KERNEL_SIZE];" +
"" +
"void main(void) {" +
" int i;" +
" vec4 sum = vec4(0.0);" +
"" +
" for (i = 0; i < MAX_KERNEL_SIZE; i++) {" +
" vec4 tmp = texture2D(baseImage," +
" gl_TexCoord[0].st + offsets[i]);" +
" sum += tmp * kernelVals[i];" +
" }" +
"" +
" gl_FragColor = sum;" +
"}";
private int blurShader;
private String brightPassShaderSource =
"uniform sampler2D baseImage;" +
"uniform float brightPassThreshold;" +
"" +
"void main(void) {" +
" vec3 luminanceVector = vec3(0.2125, 0.7154, 0.0721);" +
" vec4 sample = texture2D(baseImage, gl_TexCoord[0].st);" +
"" +
" float luminance = dot(luminanceVector, sample.rgb);" +
" luminance = max(0.0, luminance - brightPassThreshold);" +
" sample.rgb *= sign(luminance);" +
" sample.a = 1.0;" +
"" +
" gl_FragColor = sample;" +
"}";
private int brightPassShader;
private float threshold = 0.3f;
public BloomOpenGL() {
super(new GLCapabilities());
addGLEventListener(this);
try {
image = ImageIO.read(getClass().getResource("/images/screen.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void init(GLAutoDrawable glAutoDrawable) {
GL gl = glAutoDrawable.getGL();
if (texture == null) {
texture = TextureIO.newTexture(image, false);
}
// create the blur shader
blurShader = createFragmentProgram(gl, new String[] { blurShaderSource });
gl.glUseProgramObjectARB(blurShader);
int loc = gl.glGetUniformLocationARB(blurShader, "baseImage");
gl.glUniform1iARB(loc, 0);
gl.glUseProgramObjectARB(0);
// create the bright-pass shader
brightPassShader = createFragmentProgram(gl, new String[] { brightPassShaderSource });
gl.glUseProgramObjectARB(brightPassShader);
loc = gl.glGetUniformLocationARB(brightPassShader, "baseImage");
gl.glUniform1iARB(loc, 0);
gl.glUseProgramObjectARB(0);
// create the FBOs
if (gl.isExtensionAvailable("GL_EXT_framebuffer_object")) {
int[] fboId = new int[1];
int[] texId = new int[1];
createFrameBufferObject(gl, fboId, texId,
image.getWidth(), image.getHeight());
frameBufferObject1 = fboId[0];
frameBufferTexture1 = texId[0];
createFrameBufferObject(gl, fboId, texId,
image.getWidth(), image.getHeight());
frameBufferObject2 = fboId[0];
frameBufferTexture2 = texId[0];
}
}
private static void createFrameBufferObject(GL gl, int[] frameBuffer,
int[] colorBuffer, int width,
int height) {
gl.glGenFramebuffersEXT(1, frameBuffer, 0);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBuffer[0]);
gl.glGenTextures(1, colorBuffer, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, colorBuffer[0]);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA,
width, height,
0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE,
BufferUtil.newByteBuffer(width * height * 4));
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT,
GL.GL_COLOR_ATTACHMENT0_EXT,
GL.GL_TEXTURE_2D, colorBuffer[0], 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
int status = gl.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
if (status == GL.GL_FRAMEBUFFER_COMPLETE_EXT) {
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
} else {
throw new IllegalStateException("Frame Buffer Oject not created.");
}
}
private static void viewOrtho(GL gl, int width, int height) {
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho(0, width, height, 0, -1, 1);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
}
private static void renderTexturedQuad(GL gl, float width, float height,
boolean flip) {
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(0.0f, flip ? 1.0f : 0.0f);
gl.glVertex2f(0.0f, 0.0f);
gl.glTexCoord2f(1.0f, flip ? 1.0f : 0.0f);
gl.glVertex2f(width, 0.0f);
gl.glTexCoord2f(1.0f, flip ? 0.0f : 1.0f);
gl.glVertex2f(width, height);
gl.glTexCoord2f(0.0f, flip ? 0.0f : 1.0f);
gl.glVertex2f(0.0f, height);
gl.glEnd();
}
private static int createFragmentProgram(GL gl, String[] fragmentShaderSource) {
int fragmentShader, fragmentProgram;
int[] success = new int[1];
// create the shader object and compile the shader source code
fragmentShader = gl.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB);
gl.glShaderSourceARB(fragmentShader, 1, fragmentShaderSource, null);
gl.glCompileShaderARB(fragmentShader);
gl.glGetObjectParameterivARB(fragmentShader,
GL.GL_OBJECT_COMPILE_STATUS_ARB,
success, 0);
// print the compiler messages, if necessary
int[] infoLogLength = new int[1];
int[] length = new int[1];
gl.glGetObjectParameterivARB(fragmentShader,
GL.GL_OBJECT_INFO_LOG_LENGTH_ARB,
infoLogLength, 0);
if (infoLogLength[0] > 1) {
byte[] b = new byte[1024];
gl.glGetInfoLogARB(fragmentShader, 1024, length, 0, b, 0);
System.out.println("Fragment compile phase = " + new String(b, 0, length[0]));
}
if (success[0] == 0) {
gl.glDeleteObjectARB(fragmentShader);
return -1;
}
// create the program object and attach it to the shader
fragmentProgram = gl.glCreateProgramObjectARB();
gl.glAttachObjectARB(fragmentProgram, fragmentShader);
// it is now safe to delete the shader object
gl.glDeleteObjectARB(fragmentShader);
// link the program
gl.glLinkProgramARB(fragmentProgram);
gl.glGetObjectParameterivARB(fragmentProgram,
GL.GL_OBJECT_LINK_STATUS_ARB,
success, 0);
gl.glGetObjectParameterivARB(fragmentShader,
GL.GL_OBJECT_INFO_LOG_LENGTH_ARB,
infoLogLength, 0);
if (infoLogLength[0] > 1) {
byte[] b = new byte[1024];
gl.glGetInfoLogARB(fragmentShader, 1024, length, 0, b, 0);
System.out.println("Fragment link phase = " + new String(b, 0, length[0]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -