📄 bloomopengl.java
字号:
}
if (success[0] == 0) {
gl.glDeleteObjectARB(fragmentProgram);
return -1;
}
return fragmentProgram;
}
private static void enableBlurFragmentProgram(GL gl, int program,
float textureWidth,
float textureHeight) {
gl.glUseProgramObjectARB(program);
int kernelWidth = 5;
int kernelHeight = 5;
float xoff = 1.0f / textureWidth;
float yoff = 1.0f / textureHeight;
float[] offsets = new float[kernelWidth * kernelHeight * 2];
int offsetIndex = 0;
for (int i = -kernelHeight / 2; i < kernelHeight / 2 + 1; i++) {
for (int j = -kernelWidth / 2; j < kernelWidth / 2 + 1; j++) {
offsets[offsetIndex++] = j * xoff;
offsets[offsetIndex++] = i * yoff;
}
}
int loc = gl.glGetUniformLocationARB(program, "offsets");
gl.glUniform2fv(loc, offsets.length, offsets, 0);
float[] values = createGaussianBlurFilter(2);
loc = gl.glGetUniformLocationARB(program, "kernelVals");
gl.glUniform1fvARB(loc, values.length, values, 0);
}
private static float[] createGaussianBlurFilter(int radius) {
if (radius < 1) {
throw new IllegalArgumentException("Radius must be >= 1");
}
int size = radius * 2 + 1;
float[] data = new float[size * size];
float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;
int index = 0;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
float distance = x * x + y * y;
data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
index++;
}
}
for (int i = 0; i < data.length; i++) {
data[i] /= total;
}
return data;
}
private static void enableBrightPassFragmentProgram(GL gl, int program,
float threshold) {
gl.glUseProgramObjectARB(program);
int loc = gl.glGetUniformLocationARB(program, "brightPassThreshold");
gl.glUniform1fARB(loc, threshold);
}
private static void disableFragmentProgram(GL gl) {
gl.glUseProgramObjectARB(0);
}
public void display(GLAutoDrawable glAutoDrawable) {
GL gl = glAutoDrawable.getGL();
gl.glLoadIdentity();
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
viewOrtho(gl, image.getWidth(), image.getHeight());
gl.glEnable(GL.GL_TEXTURE_2D);
int width = image.getWidth();
int height = image.getHeight();
// Source Image/bright pass on FBO1
renderBrightPass(gl, width, height);
// Source image on FBO2
renderImage(gl, width, height);
// On screen
renderTextureOnScreen(gl, width, height);
//render5x5(gl, width, height);
render11x11(gl, width, height);
render21x21(gl, width, height);
render41x41(gl, width, height);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glFlush();
}
private void render41x41(GL gl, int width, int height) {
// FBO1/blur on FBO2
renderBlur(gl, width / 8.0f, height / 8.0f);
// Add on screen
gl.glPushMatrix();
gl.glTranslatef(0.0f, -height * 7.0f, 0.0f);
renderAddTextureOnScreen(gl, width * 8.0f, height * 8.0f);
gl.glPopMatrix();
}
private void render21x21(GL gl, int width, int height) {
// FBO1/blur on FBO2
renderBlur(gl, width / 4.0f, height / 4.0f);
// Add on screen
gl.glPushMatrix();
gl.glTranslatef(0.0f, -height * 3.0f, 0.0f);
renderAddTextureOnScreen(gl, width * 4.0f, height * 4.0f);
gl.glPopMatrix();
}
private void render11x11(GL gl, int width, int height) {
// FBO1/blur on FBO2
renderBlur(gl, width / 2.0f, height / 2.0f);
// Add on screen
gl.glPushMatrix();
gl.glTranslatef(0.0f, -height, 0.0f);
renderAddTextureOnScreen(gl, width * 2.0f, height * 2.0f);
gl.glPopMatrix();
}
private void render5x5(GL gl, int width, int height) {
// FBO1/blur on FBO2
renderBlur(gl, width, height);
// Add on screen
renderAddTextureOnScreen(gl, width, height);
}
private void renderAddTextureOnScreen(GL gl, float width, float height) {
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE);
renderTextureOnScreen(gl, width, height);
gl.glDisable(GL.GL_BLEND);
}
private void renderTextureOnScreen(GL gl, float width, float height) {
// Draw the texture on a quad
gl.glBindTexture(GL.GL_TEXTURE_2D, frameBufferTexture2);
renderTexturedQuad(gl, width, height, false);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
}
private void renderBrightPass(GL gl, float width, float height) {
// Draw into the FBO
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferObject1);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
enableBrightPassFragmentProgram(gl, brightPassShader, threshold);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture.getTextureObject());
renderTexturedQuad(gl, width, height, texture.getMustFlipVertically());
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
disableFragmentProgram(gl);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
}
private void renderImage(GL gl, float width, float height) {
// Draw into the FBO
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferObject2);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glBindTexture(GL.GL_TEXTURE_2D, texture.getTextureObject());
renderTexturedQuad(gl, width, height, texture.getMustFlipVertically());
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
}
private void renderBlur(GL gl, float width, float height) {
// Draw into the FBO
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferObject2);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
enableBlurFragmentProgram(gl, blurShader, width, height);
gl.glBindTexture(GL.GL_TEXTURE_2D, frameBufferTexture1);
renderTexturedQuad(gl, width, height, texture.getMustFlipVertically());
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
disableFragmentProgram(gl);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
public void reshape(GLAutoDrawable glAutoDrawable, int x, int y,
int width, int height) {
GL gl = glAutoDrawable.getGL();
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(50, (float) width / height, 5, 2000);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void displayChanged(GLAutoDrawable glAutoDrawable, boolean modeChanged,
boolean deviceChanged) {
}
public float getThreshold() {
return threshold;
}
public void setThreshold(float threshold) {
this.threshold = threshold;
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final BloomOpenGL bloom;
final JSlider slider;
JFrame f = new JFrame("Bloom OpenGL");
f.add(bloom = new BloomOpenGL());
JPanel controls = new JPanel(new FlowLayout(FlowLayout.LEADING));
controls.add(new JLabel("Bloom: 0.0"));
controls.add(slider = new JSlider(0, 100, 30));
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSlider slider = (JSlider) e.getSource();
float threshold = slider.getValue() / 100.0f;
bloom.setThreshold(threshold);
}
});
controls.add(new JLabel("1.0"));
f.add(controls, BorderLayout.SOUTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setVisible(true);
}
});
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -