From 60a2c6288c57f65222e0baa19982898d2a953552 Mon Sep 17 00:00:00 2001 From: Dan Royer Date: Mon, 18 Dec 2023 17:16:18 -0800 Subject: [PATCH] separate shaders for each RenderPass --- .../marginallyclever/ro3/DockingPanel.java | 5 + .../ro3/actions/LoadScene.java | 1 + .../ro3/node/NodeDetailView.java | 16 +- .../ro3/node/nodes/Camera.java | 39 +++- .../ro3/node/nodetreeview/NodeTreeView.java | 4 +- .../ro3/render/OpenGLPanel.java | 61 +++--- .../ro3/render/RenderPass.java | 5 +- .../marginallyclever/ro3/render/Viewport.java | 190 ++++++------------ .../render/renderpasses/DrawBackground.java | 29 ++- .../ro3/render/renderpasses/DrawCameras.java | 54 ++++- .../render/renderpasses/DrawDHParameters.java | 58 ++++-- .../render/renderpasses/DrawHingeJoints.java | 53 ++++- .../ro3/render/renderpasses/DrawMeshes.java | 50 ++++- .../ro3/render/renderpasses/DrawPoses.java | 52 ++++- .../renderpanel/OpenGLRenderPanel.java | 6 +- .../ro3/render/renderpasses/dhParameter.vert | 7 +- .../ro3/render/renderpasses/mesh.frag | 49 +++++ .../ro3/render/renderpasses/mesh.vert | 25 +++ .../renderpanel/OpenGLTestOrthographic.java | 4 +- 19 files changed, 489 insertions(+), 219 deletions(-) create mode 100644 src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.frag create mode 100644 src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.vert diff --git a/src/main/java/com/marginallyclever/ro3/DockingPanel.java b/src/main/java/com/marginallyclever/ro3/DockingPanel.java index 8631dea95..cc5d5ad94 100644 --- a/src/main/java/com/marginallyclever/ro3/DockingPanel.java +++ b/src/main/java/com/marginallyclever/ro3/DockingPanel.java @@ -29,4 +29,9 @@ public String getPersistentID() { public String getTabText() { return tabText; } + + @Override + public boolean isWrappableInScrollpane() { + return false; + } } \ No newline at end of file diff --git a/src/main/java/com/marginallyclever/ro3/actions/LoadScene.java b/src/main/java/com/marginallyclever/ro3/actions/LoadScene.java index 161105b1c..a9085cd8b 100644 --- a/src/main/java/com/marginallyclever/ro3/actions/LoadScene.java +++ b/src/main/java/com/marginallyclever/ro3/actions/LoadScene.java @@ -44,6 +44,7 @@ public void actionPerformed(ActionEvent e) { File src = (filePath != null) ? new File(filePath) // use the given filename : runFileDialog((Component) e.getSource()); // ask the user for a filename + if( src == null ) return; // cancelled loadAsNewScene(src); } diff --git a/src/main/java/com/marginallyclever/ro3/node/NodeDetailView.java b/src/main/java/com/marginallyclever/ro3/node/NodeDetailView.java index 91178f908..5e53188ed 100644 --- a/src/main/java/com/marginallyclever/ro3/node/NodeDetailView.java +++ b/src/main/java/com/marginallyclever/ro3/node/NodeDetailView.java @@ -15,8 +15,13 @@ */ public class NodeDetailView extends JPanel implements SelectionChangeListener { private static final Logger logger = LoggerFactory.getLogger(NodeDetailView.class); + private final JPanel parent = new JPanel(new BorderLayout()); + public NodeDetailView() { super(); + JScrollPane scroll = new JScrollPane(); + scroll.setViewportView(parent); + this.add(scroll, BorderLayout.CENTER); } /** @@ -26,12 +31,7 @@ public NodeDetailView() { */ @Override public void selectionChanged(List selectedNodes) { - JPanel parent = new JPanel(); - - parent.setLayout(new BorderLayout()); Box vertical = Box.createVerticalBox(); - parent.add(vertical,BorderLayout.PAGE_START); - List list = new ArrayList<>(); for(Node node : selectedNodes) { @@ -46,10 +46,8 @@ public void selectionChanged(List selectedNodes) { vertical.add(c); } - this.removeAll(); - JScrollPane scroll = new JScrollPane(); - scroll.setViewportView(parent); - this.add(scroll, BorderLayout.CENTER); + parent.removeAll(); + parent.add(vertical,BorderLayout.NORTH); this.revalidate(); this.repaint(); } diff --git a/src/main/java/com/marginallyclever/ro3/node/nodes/Camera.java b/src/main/java/com/marginallyclever/ro3/node/nodes/Camera.java index 237295bd1..f53479114 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodes/Camera.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodes/Camera.java @@ -16,10 +16,10 @@ import java.util.List; public class Camera extends Pose { + private boolean drawOrthographic = false; private double fovY = 60; private double nearZ = 1; private double farZ = 1000; - private boolean drawOrthographic = false; public Camera() { super("Camera"); @@ -195,4 +195,41 @@ public void lookAt(Vector3d target) { local.setTranslation(position); this.setLocal(local); } + + public Matrix4d getPerspectiveFrustum(int width,int height) { + double nearVal = this.getNearZ(); + double farVal = this.getFarZ(); + double aspect = (double)width / (double)height; + + return MatrixHelper.perspectiveMatrix4d(this.getFovY(),aspect,nearVal,farVal); + } + + /** + * Render the scene in orthographic projection. + * @param zoom the zoom factor + */ + public Matrix4d getOrthographicMatrix(double zoom,int width,int height) { + double w = width/2.0f; + double h = height/2.0f; + + double left = -w/zoom; + double right = w/zoom; + double bottom = -h/zoom; + double top = h/zoom; + double nearVal = this.getNearZ(); + double farVal = this.getFarZ(); + + return MatrixHelper.orthographicMatrix4d(left,right,bottom,top,nearVal,farVal); + } + + public Matrix4d getChosenProjectionMatrix(int width,int height) { + return drawOrthographic ? getOrthographicMatrix(1.0,width,height) : getPerspectiveFrustum(width,height); + } + + public Matrix4d getViewMatrix() { + Matrix4d inverseCamera = this.getWorld(); + inverseCamera.invert(); + inverseCamera.transpose(); + return inverseCamera; + } } diff --git a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java index 7464f8cd8..d62833a4d 100644 --- a/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java +++ b/src/main/java/com/marginallyclever/ro3/node/nodetreeview/NodeTreeView.java @@ -43,7 +43,9 @@ public NodeTreeView() { buildMenuBar(); - add(tree, BorderLayout.CENTER); + JScrollPane scroll = new JScrollPane(); + scroll.setViewportView(tree); + add(scroll, BorderLayout.CENTER); add(menuBar, BorderLayout.NORTH); } diff --git a/src/main/java/com/marginallyclever/ro3/render/OpenGLPanel.java b/src/main/java/com/marginallyclever/ro3/render/OpenGLPanel.java index 467f924e3..b94d96392 100644 --- a/src/main/java/com/marginallyclever/ro3/render/OpenGLPanel.java +++ b/src/main/java/com/marginallyclever/ro3/render/OpenGLPanel.java @@ -29,11 +29,10 @@ /** * {@link OpenGLPanel} is a {@link DockingPanel} that contains a {@link GLJPanel} and an {@link FPSAnimator}. */ -public class OpenGLPanel extends JPanel implements GLEventListener, MouseListener, MouseMotionListener, MouseWheelListener { +public class OpenGLPanel extends JPanel implements GLEventListener, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener { private static final Logger logger = LoggerFactory.getLogger(OpenGLPanel.class); protected GLJPanel glCanvas; protected int canvasWidth, canvasHeight; - protected ShaderProgram shaderDefault; private final FPSAnimator animator = new FPSAnimator(GraphicsPreferences.framesPerSecond.get()); private final List listeners = new ArrayList<>(); @@ -60,6 +59,7 @@ public void addNotify() { glCanvas.addMouseListener(this); glCanvas.addMouseMotionListener(this); glCanvas.addMouseWheelListener(this); + glCanvas.addKeyListener(this); } @Override @@ -69,6 +69,7 @@ public void removeNotify() { glCanvas.removeMouseListener(this); glCanvas.removeMouseMotionListener(this); glCanvas.removeMouseWheelListener(this); + glCanvas.removeKeyListener(this); } private GLCapabilities getCapabilities() { @@ -136,32 +137,12 @@ public void init(GLAutoDrawable glAutoDrawable) { gl3.glBlendFunc(GL3.GL_SRC_ALPHA, GL3.GL_ONE_MINUS_SRC_ALPHA); gl3.glActiveTexture(GL3.GL_TEXTURE0); - - // create the default shader - try { - shaderDefault = new ShaderProgram(gl3, - ResourceHelper.readResource(this.getClass(),"default_330.vert"), - ResourceHelper.readResource(this.getClass(),"default_330.frag")); - } catch(IOException e) { - logger.error("Failed to create default shader.",e); - } - shaderDefault.use(gl3); - shaderDefault.setVector3d(gl3,"lightColor",new Vector3d(1,1,1)); // Light color - shaderDefault.set4f(gl3,"objectColor",1,1,1,1); - shaderDefault.setVector3d(gl3,"specularColor",new Vector3d(0.5,0.5,0.5)); - shaderDefault.setVector3d(gl3,"ambientLightColor",new Vector3d(0.2,0.2,0.2)); - shaderDefault.set1f(gl3,"useVertexColor",0); - shaderDefault.set1i(gl3,"useLighting",1); - shaderDefault.set1i(gl3,"useTexture",0); - shaderDefault.set1i(gl3,"diffuseTexture",0); - OpenGLHelper.checkGLError(gl3,logger); } @Override public void dispose(GLAutoDrawable glAutoDrawable) { logger.info("dispose"); GL3 gl3 = glAutoDrawable.getGL().getGL3(); - shaderDefault.delete(gl3); unloadAllMeshes(gl3); Registry.textureFactory.unloadAll(); } @@ -189,18 +170,7 @@ public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int } @Override - public void display(GLAutoDrawable glAutoDrawable) { - renderAllPasses(); - } - - private void renderAllPasses() { - // renderPasses that are always on - for(RenderPass pass : Registry.renderPasses.getList()) { - if(pass.getActiveStatus()==RenderPass.ALWAYS) { - pass.draw(shaderDefault); - } - } - } + public void display(GLAutoDrawable glAutoDrawable) {} @Override public void mouseClicked(MouseEvent e) {} @@ -225,4 +195,27 @@ public void mouseMoved(MouseEvent e) {} @Override public void mouseWheelMoved(MouseWheelEvent e) {} + + public int getCanvasHeight() { + return canvasHeight; + } + + public int getCanvasWidth() { + return canvasWidth; + } + + @Override + public void keyTyped(KeyEvent e) { + System.out.println("keyTyped "+e); + } + + @Override + public void keyPressed(KeyEvent e) { + System.out.println("keyPressed "+e); + } + + @Override + public void keyReleased(KeyEvent e) { + System.out.println("keyReleased "+e); + } } diff --git a/src/main/java/com/marginallyclever/ro3/render/RenderPass.java b/src/main/java/com/marginallyclever/ro3/render/RenderPass.java index d68df4574..f4fd47083 100644 --- a/src/main/java/com/marginallyclever/ro3/render/RenderPass.java +++ b/src/main/java/com/marginallyclever/ro3/render/RenderPass.java @@ -1,5 +1,6 @@ package com.marginallyclever.ro3.render; +import com.jogamp.opengl.GLEventListener; import com.marginallyclever.ro3.Registry; import com.marginallyclever.robotoverlord.systems.render.ShaderProgram; @@ -7,7 +8,7 @@ * Classes which implement {@link RenderPass} are drawn on top of the 3D scene. They should be registered to the * {@link Registry}, which remembers the order in which they should be drawn. */ -public interface RenderPass { +public interface RenderPass extends GLEventListener { int NEVER = 0; int SOMETIMES = 1; int ALWAYS = 2; @@ -28,5 +29,5 @@ public interface RenderPass { */ String getName(); - void draw(ShaderProgram shader); + void draw(); } diff --git a/src/main/java/com/marginallyclever/ro3/render/Viewport.java b/src/main/java/com/marginallyclever/ro3/render/Viewport.java index e72e32c9e..958c68361 100644 --- a/src/main/java/com/marginallyclever/ro3/render/Viewport.java +++ b/src/main/java/com/marginallyclever/ro3/render/Viewport.java @@ -1,10 +1,8 @@ package com.marginallyclever.ro3.render; -import com.jogamp.opengl.GL3; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.marginallyclever.convenience.helpers.MatrixHelper; -import com.marginallyclever.convenience.helpers.OpenGLHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.Node; import com.marginallyclever.ro3.node.nodes.Camera; @@ -17,7 +15,6 @@ import javax.vecmath.Vector3d; import java.awt.*; import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; import java.util.ArrayList; import java.util.List; @@ -56,27 +53,7 @@ private void addRenderPassSelection() { button.addActionListener(e -> overlayMenu.show(button, button.getWidth()/2, button.getHeight()/2)); for(RenderPass renderPass : Registry.renderPasses.getList()) { - addOverlayInternal(renderPass); - } - } - - private void addOverlayInternal(RenderPass renderPass) { - JCheckBox checkBox = new JCheckBox(renderPass.getName()); - checkBox.setSelected(renderPass.getActiveStatus() == RenderPass.ALWAYS); - checkBox.addActionListener(e -> { - renderPass.setActiveStatus(checkBox.isSelected() ? RenderPass.ALWAYS : RenderPass.NEVER); - }); - overlayMenu.add(checkBox); - } - - private void removeOverlayInternal(RenderPass renderPass) { - for(Component c : overlayMenu.getComponents()) { - if(c instanceof JCheckBox checkBox) { - if(checkBox.getText().equals(renderPass.getName())) { - overlayMenu.remove(c); - return; - } - } + addRenderPass(renderPass); } } @@ -85,8 +62,8 @@ public void addNotify() { super.addNotify(); Registry.cameras.addItemAddedListener(this::addCamera); Registry.cameras.addItemRemovedListener(this::removeCamera); - Registry.renderPasses.addItemAddedListener(this::addOverlay); - Registry.renderPasses.addItemRemovedListener(this::removeOverlay); + Registry.renderPasses.addItemAddedListener(this::addRenderPass); + Registry.renderPasses.addItemRemovedListener(this::removeRenderPass); } @Override @@ -94,18 +71,38 @@ public void removeNotify() { super.removeNotify(); Registry.cameras.removeItemAddedListener(this::addCamera); Registry.cameras.removeItemRemovedListener(this::removeCamera); - Registry.renderPasses.removeItemAddedListener(this::addOverlay); - Registry.renderPasses.removeItemRemovedListener(this::removeOverlay); + Registry.renderPasses.removeItemAddedListener(this::addRenderPass); + Registry.renderPasses.removeItemRemovedListener(this::removeRenderPass); + } + + private void addRenderPass(RenderPass renderPass) { + addRenderPassInternal(renderPass); + addGLEventListener(renderPass); } - private void addOverlay(RenderPass renderPass) { - addOverlayInternal(renderPass); - //addGLEventListener(overlay); + private void removeRenderPass(RenderPass renderPass) { + removeRenderPassInternal(renderPass); + removeGLEventListener(renderPass); + } + + private void addRenderPassInternal(RenderPass renderPass) { + JCheckBox checkBox = new JCheckBox(renderPass.getName()); + checkBox.setSelected(renderPass.getActiveStatus() == RenderPass.ALWAYS); + checkBox.addActionListener(e -> { + renderPass.setActiveStatus(checkBox.isSelected() ? RenderPass.ALWAYS : RenderPass.NEVER); + }); + overlayMenu.add(checkBox); } - private void removeOverlay(RenderPass renderPass) { - removeOverlayInternal(renderPass); - //removeGLEventListener(overlay); + private void removeRenderPassInternal(RenderPass renderPass) { + for(Component c : overlayMenu.getComponents()) { + if(c instanceof JCheckBox checkBox) { + if(checkBox.getText().equals(renderPass.getName())) { + overlayMenu.remove(c); + return; + } + } + } } private void addCamera(Camera camera) { @@ -141,42 +138,6 @@ public Component getListCellRendererComponent(JList list, Object value, int i toolBar.add(cameraSelector); } - public Matrix4d getPerspectiveFrustum() { - double nearVal = camera.getNearZ(); - double farVal = camera.getFarZ(); - double aspect = (double)canvasWidth / (double)canvasHeight; - - return MatrixHelper.perspectiveMatrix4d(camera.getFovY(),aspect,nearVal,farVal); - } - - /** - * Render the scene in orthographic projection. - * @param zoom the zoom factor - */ - public Matrix4d getOrthographicMatrix(double zoom) { - double w = canvasWidth/2.0f; - double h = canvasHeight/2.0f; - - double left = -w/zoom; - double right = w/zoom; - double bottom = -h/zoom; - double top = h/zoom; - double nearVal = camera.getNearZ(); - double farVal = camera.getFarZ(); - - return MatrixHelper.orthographicMatrix4d(left,right,bottom,top,nearVal,farVal); - } - - public Matrix4d getChosenProjectionMatrix() { - return camera.getDrawOrthographic() ? getOrthographicMatrix(1.0) : getPerspectiveFrustum(); - } - - private Matrix4d getViewMatrix() { - Matrix4d inverseCamera = camera.getWorld(); - inverseCamera.invert(); - return inverseCamera; - } - @Override public void init(GLAutoDrawable glAutoDrawable) { super.init(glAutoDrawable); @@ -196,26 +157,16 @@ public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int public void display(GLAutoDrawable glAutoDrawable) { double dt = 0.03; updateAllNodes(dt); + renderAllPasses(); + } - if (camera == null) return; - if (shaderDefault == null) return; - - Matrix4d w = camera.getWorld(); - Vector3d cameraWorldPos = MatrixHelper.getPosition(w); - - GL3 gl3 = glAutoDrawable.getGL().getGL3(); - shaderDefault.use(gl3); - Matrix4d viewMatrix = getViewMatrix(); - viewMatrix.transpose(); - shaderDefault.setMatrix4d(gl3,"viewMatrix",viewMatrix); - Matrix4d projectionMatrix = getChosenProjectionMatrix(); - shaderDefault.setMatrix4d(gl3,"projectionMatrix",projectionMatrix); - shaderDefault.setVector3d(gl3,"cameraPos",cameraWorldPos); // Camera position in world space - shaderDefault.setVector3d(gl3,"lightPos",cameraWorldPos); // Light position in world space - OpenGLHelper.checkGLError(gl3,logger); - - // render all passes - super.display(glAutoDrawable); + private void renderAllPasses() { + // renderPasses that are always on + for(RenderPass pass : Registry.renderPasses.getList()) { + if(pass.getActiveStatus()==RenderPass.ALWAYS) { + pass.draw(); + } + } } private void updateAllNodes(double dt) { @@ -227,9 +178,6 @@ private void updateAllNodes(double dt) { } } - @Override - public void mouseClicked(MouseEvent e) {} - @Override public void mousePressed(MouseEvent e) { buttonPressed.set(e.getButton(),true); @@ -242,12 +190,6 @@ public void mouseReleased(MouseEvent e) { buttonPressed.set(e.getButton(),false); } - @Override - public void mouseEntered(MouseEvent e) {} - - @Override - public void mouseExited(MouseEvent e) {} - @Override public void mouseDragged(MouseEvent e) { int px = e.getX(); @@ -259,30 +201,36 @@ public void mouseDragged(MouseEvent e) { my = py; if(buttonPressed.get(MouseEvent.BUTTON1)) {} - if(buttonPressed.get(MouseEvent.BUTTON2)) { - // middle button - Matrix4d local = camera.getLocal(); - double [] panTiltAngles = getPanTiltFromMatrix(local); - double beforePan = (panTiltAngles[0]+360) % 360; - double beforeTilt = ((panTiltAngles[1]+90) % 360) -90; - panTiltAngles[0] = beforePan + dx; - panTiltAngles[1] = beforeTilt + dy; - panTiltAngles[1] = Math.max(0,Math.min(180,panTiltAngles[1])); - System.out.println("before= "+beforePan+","+beforeTilt+"\tafter=" + panTiltAngles[0] + "," + panTiltAngles[1] + "\tdiff="+dx+","+dy); - Matrix3d panTilt = buildPanTiltMatrix(panTiltAngles); - Vector3d t = new Vector3d(); - local.get(t); - local.set(panTilt); - local.setTranslation(t); - camera.setLocal(local); + if(buttonPressed.get(MouseEvent.BUTTON2)) { // middle button + panTiltCamera(dx,dy); } - if(buttonPressed.get(MouseEvent.BUTTON3)) { - // right button - camera.truck(-dx); - camera.dolly(dy); + if(buttonPressed.get(MouseEvent.BUTTON3)) { // right button + moveCamera(dx,dy); } } + private void panTiltCamera(int dx, int dy) { + Matrix4d local = camera.getLocal(); + double [] panTiltAngles = getPanTiltFromMatrix(local); + double beforePan = (panTiltAngles[0]+360) % 360; + double beforeTilt = ((panTiltAngles[1]+90) % 360) -90; + panTiltAngles[0] = beforePan + dx; + panTiltAngles[1] = beforeTilt + dy; + panTiltAngles[1] = Math.max(0,Math.min(180,panTiltAngles[1])); + System.out.println("before= "+beforePan+","+beforeTilt+"\tafter=" + panTiltAngles[0] + "," + panTiltAngles[1] + "\tdiff="+dx+","+dy); + Matrix3d panTilt = buildPanTiltMatrix(panTiltAngles); + Vector3d t = new Vector3d(); + local.get(t); + local.set(panTilt); + local.setTranslation(t); + camera.setLocal(local); + } + + private void moveCamera(int dx,int dy) { + camera.truck(-dx); + camera.dolly(dy); + } + public double[] getPanTiltFromMatrix(Matrix4d matrix) { Vector3d v = MatrixHelper.matrixToEuler(matrix); double pan = Math.toDegrees(-v.z); @@ -306,10 +254,4 @@ public Matrix3d buildPanTiltMatrix(double [] panTiltAngles) { c.transpose(); return c; } - - @Override - public void mouseMoved(MouseEvent e) {} - - @Override - public void mouseWheelMoved(MouseWheelEvent e) {} } diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawBackground.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawBackground.java index e5551487f..7f39715ec 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawBackground.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawBackground.java @@ -2,6 +2,7 @@ import com.jogamp.opengl.GL; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; import com.marginallyclever.convenience.ColorRGB; import com.marginallyclever.ro3.render.RenderPass; @@ -36,17 +37,27 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { - GL3 gl = GLContext.getCurrentGL().getGL3(); - gl.glClearColor(eraseColor.red/255.0f, + public void init(GLAutoDrawable glAutoDrawable) {} + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) {} + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) {} + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { + GL3 gl3 = GLContext.getCurrentGL().getGL3(); + gl3.glClearColor(eraseColor.red/255.0f, eraseColor.green/255.0f, eraseColor.blue/255.0f, 1); - - gl.glDepthMask(true); - gl.glColorMask(true,true,true,true); - gl.glStencilMask(0xFF); - - gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); + gl3.glDepthMask(true); + gl3.glColorMask(true,true,true,true); + gl3.glStencilMask(0xFF); + gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); } } diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawCameras.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawCameras.java index c8e418245..95546271e 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawCameras.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawCameras.java @@ -1,13 +1,17 @@ package com.marginallyclever.ro3.render.renderpasses; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; import com.marginallyclever.convenience.helpers.MatrixHelper; +import com.marginallyclever.convenience.helpers.ResourceHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.nodes.Camera; import com.marginallyclever.ro3.render.RenderPass; import com.marginallyclever.robotoverlord.systems.render.ShaderProgram; import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.vecmath.Matrix4d; import javax.vecmath.Vector3d; @@ -16,8 +20,11 @@ * Draws each {@link Camera} as a pyramid approximating the perspective view frustum. */ public class DrawCameras implements RenderPass { + private static final Logger logger = LoggerFactory.getLogger(DrawCameras.class); private int activeStatus = ALWAYS; private final Mesh mesh = new Mesh(); + private ShaderProgram shader; + private int canvasWidth,canvasHeight; public DrawCameras() { // add mesh to a list that can be unloaded and reloaded as needed. @@ -65,25 +72,60 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { + public void init(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + try { + shader = new ShaderProgram(gl3, + ResourceHelper.readResource(this.getClass(), "mesh.vert"), + ResourceHelper.readResource(this.getClass(), "mesh.frag")); + } catch(Exception e) { + logger.error("Failed to load shader", e); + } + } + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + shader.delete(gl3); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { + canvasWidth = width; + canvasHeight = height; + } + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { GL3 gl3 = GLContext.getCurrentGL().getGL3(); shader.use(gl3); + Camera camera = Registry.cameras.getList().get(0); + shader.setMatrix4d(gl3,"projectionMatrix",camera.getChosenProjectionMatrix(canvasWidth,canvasHeight)); + shader.setMatrix4d(gl3,"viewMatrix",camera.getViewMatrix()); + Vector3d cameraWorldPos = MatrixHelper.getPosition(camera.getWorld()); + shader.setVector3d(gl3,"cameraPos",cameraWorldPos); // Camera position in world space + shader.setVector3d(gl3,"lightPos",cameraWorldPos); // Light position in world space + shader.setVector3d(gl3,"lightColor",new Vector3d(1,1,1)); // Light color + shader.set4f(gl3,"objectColor",1,1,1,1); + shader.setVector3d(gl3,"specularColor",new Vector3d(0.5,0.5,0.5)); + shader.setVector3d(gl3,"ambientLightColor",new Vector3d(0.2,0.2,0.2)); shader.set1f(gl3,"useVertexColor",1); shader.set1i(gl3,"useLighting",0); - shader.set1i(gl3,"useTexture",0); + shader.set1i(gl3,"diffuseTexture",0); gl3.glDisable(GL3.GL_DEPTH_TEST); gl3.glDisable(GL3.GL_TEXTURE_2D); - for(Camera camera : Registry.cameras.getList() ) { + for(Camera cam : Registry.cameras.getList() ) { // set modelView to world - Matrix4d w = camera.getWorld(); + Matrix4d w = cam.getWorld(); w.transpose(); shader.setMatrix4d(gl3,"modelMatrix",w); mesh.render(gl3); } - shader.set1f(gl3,"useVertexColor",0); - shader.set1i(gl3,"useLighting",1); gl3.glEnable(GL3.GL_DEPTH_TEST); } } diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawDHParameters.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawDHParameters.java index f709c96fe..bdd3d1875 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawDHParameters.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawDHParameters.java @@ -1,6 +1,7 @@ package com.marginallyclever.ro3.render.renderpasses; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; import com.marginallyclever.convenience.helpers.MatrixHelper; import com.marginallyclever.convenience.helpers.ResourceHelper; @@ -12,6 +13,8 @@ import com.marginallyclever.ro3.render.RenderPass; import com.marginallyclever.robotoverlord.systems.render.ShaderProgram; import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.vecmath.Matrix4d; import javax.vecmath.Vector3d; @@ -23,9 +26,11 @@ * Draws each {@link DHParameter} as two lines from the previous joint to the current joint. */ public class DrawDHParameters implements RenderPass { + private static final Logger logger = LoggerFactory.getLogger(DrawDHParameters.class); private int activeStatus = ALWAYS; private final Mesh mesh = new Mesh(); - private ShaderProgram myShader; + private ShaderProgram shader; + private int canvasWidth,canvasHeight; public DrawDHParameters() { // add mesh to a list that can be unloaded and reloaded as needed. @@ -63,22 +68,41 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { - GL3 gl3 = GLContext.getCurrentGL().getGL3(); - if(myShader==null) { - try { - myShader = new ShaderProgram(gl3, - ResourceHelper.readResource(this.getClass(),"dhParameter.vert"), - ResourceHelper.readResource(this.getClass(),"dhParameter.frag")); - } catch(IOException e) { - //logger.error("Failed to create default shader.",e); - } + public void init(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + try { + shader = new ShaderProgram(gl3, + ResourceHelper.readResource(this.getClass(),"dhParameter.vert"), + ResourceHelper.readResource(this.getClass(),"dhParameter.frag")); + } catch(IOException e) { + logger.error("Failed to create default shader.",e); } - if(myShader==null) return; + } + @Override + public void dispose(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + shader.delete(gl3); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { + canvasWidth = width; + canvasHeight = height; + } + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { + GL3 gl3 = GLContext.getCurrentGL().getGL3(); gl3.glDisable(GL3.GL_DEPTH_TEST); gl3.glDisable(GL3.GL_TEXTURE_2D); - myShader.use(gl3); + shader.use(gl3); + Camera camera = Registry.cameras.getList().get(0); + shader.setMatrix4d(gl3,"projectionMatrix",camera.getChosenProjectionMatrix(canvasWidth,canvasHeight)); + shader.setMatrix4d(gl3,"viewMatrix",camera.getViewMatrix()); List toScan = new ArrayList<>(); toScan.add(Registry.getScene()); @@ -93,10 +117,10 @@ public void draw(ShaderProgram shader) { ? MatrixHelper.createIdentityMatrix4() : parentPose.getWorld(); w.transpose(); - myShader.setMatrix4d(gl3,"modelMatrix",w); - myShader.set1f(gl3,"d",(float)parameter.getD()); - myShader.set1f(gl3,"theta",(float)parameter.getTheta()); - myShader.set1f(gl3,"r",(float)parameter.getR()); + shader.setMatrix4d(gl3,"modelMatrix",w); + shader.set1f(gl3,"d",(float)parameter.getD()); + shader.set1f(gl3,"theta",(float)parameter.getTheta()); + shader.set1f(gl3,"r",(float)parameter.getR()); //myShader.set1f(gl3,"alpha",(float)parameter.getAlpha()); mesh.render(gl3); } diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawHingeJoints.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawHingeJoints.java index f5a67d6c8..845750d32 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawHingeJoints.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawHingeJoints.java @@ -1,21 +1,31 @@ package com.marginallyclever.ro3.render.renderpasses; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; +import com.marginallyclever.convenience.helpers.MatrixHelper; +import com.marginallyclever.convenience.helpers.ResourceHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.Node; +import com.marginallyclever.ro3.node.nodes.Camera; import com.marginallyclever.ro3.node.nodes.HingeJoint; import com.marginallyclever.ro3.render.RenderPass; import com.marginallyclever.robotoverlord.systems.render.ShaderProgram; import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.vecmath.Matrix4d; +import javax.vecmath.Vector3d; import java.util.ArrayList; import java.util.List; public class DrawHingeJoints implements RenderPass { + private static final Logger logger = LoggerFactory.getLogger(DrawHingeJoints.class); private int activeStatus = ALWAYS; private final Mesh mesh = new Mesh(); + private ShaderProgram shader; + private int canvasWidth,canvasHeight; public DrawHingeJoints() { super(); @@ -45,12 +55,49 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { + public void init(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + try { + shader = new ShaderProgram(gl3, + ResourceHelper.readResource(this.getClass(), "mesh.vert"), + ResourceHelper.readResource(this.getClass(), "mesh.frag")); + } catch(Exception e) { + logger.error("Failed to load shader", e); + } + } + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + shader.delete(gl3); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { + canvasWidth = width; + canvasHeight = height; + } + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { GL3 gl3 = GLContext.getCurrentGL().getGL3(); shader.use(gl3); + Camera camera = Registry.cameras.getList().get(0); + shader.setMatrix4d(gl3,"projectionMatrix",camera.getChosenProjectionMatrix(canvasWidth,canvasHeight)); + shader.setMatrix4d(gl3,"viewMatrix",camera.getViewMatrix()); + Vector3d cameraWorldPos = MatrixHelper.getPosition(camera.getWorld()); + shader.setVector3d(gl3,"cameraPos",cameraWorldPos); // Camera position in world space + shader.setVector3d(gl3,"lightPos",cameraWorldPos); // Light position in world space + shader.setVector3d(gl3,"lightColor",new Vector3d(1,1,1)); // Light color + shader.set4f(gl3,"objectColor",1,1,1,1); + shader.setVector3d(gl3,"specularColor",new Vector3d(0.5,0.5,0.5)); + shader.setVector3d(gl3,"ambientLightColor",new Vector3d(0.2,0.2,0.2)); shader.set1f(gl3,"useVertexColor",1); shader.set1i(gl3,"useLighting",0); - shader.set1i(gl3,"useTexture",0); + shader.set1i(gl3,"diffuseTexture",0); gl3.glDisable(GL3.GL_DEPTH_TEST); gl3.glDisable(GL3.GL_TEXTURE_2D); @@ -68,8 +115,6 @@ public void draw(ShaderProgram shader) { } } - shader.set1f(gl3,"useVertexColor",0); - shader.set1i(gl3,"useLighting",1); gl3.glEnable(GL3.GL_DEPTH_TEST); } } diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawMeshes.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawMeshes.java index 9a058ba22..558373d69 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawMeshes.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawMeshes.java @@ -1,10 +1,14 @@ package com.marginallyclever.ro3.render.renderpasses; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; +import com.marginallyclever.convenience.helpers.MatrixHelper; import com.marginallyclever.convenience.helpers.OpenGLHelper; +import com.marginallyclever.convenience.helpers.ResourceHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.Node; +import com.marginallyclever.ro3.node.nodes.Camera; import com.marginallyclever.ro3.node.nodes.Material; import com.marginallyclever.ro3.node.nodes.MeshInstance; import com.marginallyclever.ro3.render.RenderPass; @@ -15,6 +19,7 @@ import org.slf4j.LoggerFactory; import javax.vecmath.Matrix4d; +import javax.vecmath.Vector3d; import java.util.ArrayList; import java.util.List; @@ -25,6 +30,8 @@ public class DrawMeshes implements RenderPass { private static final Logger logger = LoggerFactory.getLogger(DrawMeshes.class); private int activeStatus = ALWAYS; + private ShaderProgram shader; + private int canvasWidth, canvasHeight; /** * @return NEVER, SOMETIMES, or ALWAYS @@ -51,9 +58,50 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { + public void init(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + try { + shader = new ShaderProgram(gl3, + ResourceHelper.readResource(this.getClass(), "mesh.vert"), + ResourceHelper.readResource(this.getClass(), "mesh.frag")); + } catch(Exception e) { + logger.error("Failed to load shader", e); + } + } + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + shader.delete(gl3); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { + canvasWidth = width; + canvasHeight = height; + } + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { GL3 gl3 = GLContext.getCurrentGL().getGL3(); shader.use(gl3); + Camera camera = Registry.cameras.getList().get(0); + shader.setMatrix4d(gl3,"viewMatrix",camera.getViewMatrix()); + shader.setMatrix4d(gl3,"projectionMatrix",camera.getChosenProjectionMatrix(canvasWidth,canvasHeight)); + Vector3d cameraWorldPos = MatrixHelper.getPosition(camera.getWorld()); + shader.setVector3d(gl3,"cameraPos",cameraWorldPos); // Camera position in world space + shader.setVector3d(gl3,"lightPos",cameraWorldPos); // Light position in world space + shader.setVector3d(gl3,"lightColor",new Vector3d(1,1,1)); // Light color + shader.set4f(gl3,"objectColor",1,1,1,1); + shader.setVector3d(gl3,"specularColor",new Vector3d(0.5,0.5,0.5)); + shader.setVector3d(gl3,"ambientLightColor",new Vector3d(0.2,0.2,0.2)); + shader.set1f(gl3,"useVertexColor",0); + shader.set1i(gl3,"useLighting",1); + shader.set1i(gl3,"diffuseTexture",0); + OpenGLHelper.checkGLError(gl3,logger); // find all MeshInstance nodes in Registry List toScan = new ArrayList<>(Registry.getScene().getChildren()); diff --git a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawPoses.java b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawPoses.java index 542575220..af3ba5be7 100644 --- a/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawPoses.java +++ b/src/main/java/com/marginallyclever/ro3/render/renderpasses/DrawPoses.java @@ -1,16 +1,22 @@ package com.marginallyclever.ro3.render.renderpasses; import com.jogamp.opengl.GL3; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLContext; import com.marginallyclever.convenience.helpers.MatrixHelper; +import com.marginallyclever.convenience.helpers.ResourceHelper; import com.marginallyclever.ro3.Registry; import com.marginallyclever.ro3.node.Node; +import com.marginallyclever.ro3.node.nodes.Camera; import com.marginallyclever.ro3.node.nodes.Pose; import com.marginallyclever.ro3.render.RenderPass; import com.marginallyclever.robotoverlord.systems.render.ShaderProgram; import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.vecmath.Matrix4d; +import javax.vecmath.Vector3d; import java.util.ArrayList; import java.util.List; @@ -18,8 +24,11 @@ * Draw each {@link Pose} as RGB lines from the origin to the X,Y,Z axes. */ public class DrawPoses implements RenderPass { + private static final Logger logger = LoggerFactory.getLogger(DrawPoses.class); private int activeStatus = ALWAYS; private final Mesh mesh = MatrixHelper.createMesh(1.0); + private ShaderProgram shader; + private int canvasWidth,canvasHeight; /** * @return NEVER, SOMETIMES, or ALWAYS @@ -46,12 +55,49 @@ public String getName() { } @Override - public void draw(ShaderProgram shader) { + public void init(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + try { + shader = new ShaderProgram(gl3, + ResourceHelper.readResource(this.getClass(), "mesh.vert"), + ResourceHelper.readResource(this.getClass(), "mesh.frag")); + } catch(Exception e) { + logger.error("Failed to load shader", e); + } + } + + @Override + public void dispose(GLAutoDrawable glAutoDrawable) { + GL3 gl3 = glAutoDrawable.getGL().getGL3(); + shader.delete(gl3); + } + + @Override + public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) { + canvasWidth = width; + canvasHeight = height; + } + + @Override + public void display(GLAutoDrawable glAutoDrawable) {} + + @Override + public void draw() { GL3 gl3 = GLContext.getCurrentGL().getGL3(); shader.use(gl3); + Camera camera = Registry.cameras.getList().get(0); + shader.setMatrix4d(gl3,"projectionMatrix",camera.getChosenProjectionMatrix(canvasWidth,canvasHeight)); + shader.setMatrix4d(gl3,"viewMatrix",camera.getViewMatrix()); + Vector3d cameraWorldPos = MatrixHelper.getPosition(camera.getWorld()); + shader.setVector3d(gl3,"cameraPos",cameraWorldPos); // Camera position in world space + shader.setVector3d(gl3,"lightPos",cameraWorldPos); // Light position in world space + shader.setVector3d(gl3,"lightColor",new Vector3d(1,1,1)); // Light color + shader.set4f(gl3,"objectColor",1,1,1,1); + shader.setVector3d(gl3,"specularColor",new Vector3d(0.5,0.5,0.5)); + shader.setVector3d(gl3,"ambientLightColor",new Vector3d(0.2,0.2,0.2)); shader.set1f(gl3,"useVertexColor",1); shader.set1i(gl3,"useLighting",0); - shader.set1i(gl3,"useTexture",0); + shader.set1i(gl3,"diffuseTexture",0); gl3.glDisable(GL3.GL_DEPTH_TEST); gl3.glDisable(GL3.GL_TEXTURE_2D); @@ -69,8 +115,6 @@ public void draw(ShaderProgram shader) { } } - shader.set1f(gl3,"useVertexColor",0); - shader.set1i(gl3,"useLighting",1); gl3.glEnable(GL3.GL_DEPTH_TEST); } } diff --git a/src/main/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLRenderPanel.java b/src/main/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLRenderPanel.java index 1807427ec..979dcc8f9 100644 --- a/src/main/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLRenderPanel.java +++ b/src/main/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLRenderPanel.java @@ -383,13 +383,13 @@ public void keyReleased(KeyEvent e) { private void createShaderPrograms(GL3 gl3) { shaderDefault = new ShaderProgram(gl3, - readResource("default_330.vert"), - readResource("default_330.frag")); + readResource("mesh.vert"), + readResource("mesh.frag")); shaderOutline = new ShaderProgram(gl3, readResource("outline_330.vert"), readResource("outline_330.frag")); shaderHUD = new ShaderProgram(gl3, - readResource("default_330.vert"), + readResource("mesh.vert"), readResource("givenColor_330.frag")); } diff --git a/src/main/resources/com/marginallyclever/ro3/render/renderpasses/dhParameter.vert b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/dhParameter.vert index 0cddcc09c..ff352df8d 100644 --- a/src/main/resources/com/marginallyclever/ro3/render/renderpasses/dhParameter.vert +++ b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/dhParameter.vert @@ -1,11 +1,14 @@ #version 330 core -uniform mat4 modelMatrix; uniform float d; uniform float theta; uniform float r; uniform float alpha; +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform mat4 modelMatrix; + in vec3 position; void main() { @@ -19,5 +22,5 @@ void main() { newPosition.x += r; // Apply the world matrix - gl_Position = modelMatrix * vec4(newPosition, 1.0); + gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(newPosition, 1.0); } \ No newline at end of file diff --git a/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.frag b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.frag new file mode 100644 index 000000000..66d45e1a7 --- /dev/null +++ b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.frag @@ -0,0 +1,49 @@ +#version 330 core + +in vec4 fragmentColor; +in vec3 normalVector; +in vec3 fragmentPosition; +in vec2 textureCoord; + +out vec4 finalColor; + +uniform vec3 specularColor = vec3(0.5, 0.5, 0.5); +uniform vec3 ambientLightColor = vec3(0.2, 0.2, 0.2); +uniform vec3 lightPos; // Light position in world space +uniform vec3 cameraPos; // Camera position in world space +uniform vec4 objectColor; +uniform vec3 lightColor; +uniform sampler2D diffuseTexture; + +uniform bool useTexture; +uniform bool useLighting; +uniform bool useVertexColor; // per-vertex color + +void main() { + vec4 diffuseColor = objectColor; + if(useVertexColor) diffuseColor *= fragmentColor; + if(useTexture) diffuseColor *= texture(diffuseTexture, textureCoord); + + vec3 result = vec3(diffuseColor); + + if(useLighting) { + vec3 norm = normalize(normalVector); + vec3 lightDir = normalize(lightPos - fragmentPosition); + + // Diffuse + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuseLight = diff * lightColor; + + // Specular + vec3 viewDir = normalize(cameraPos - fragmentPosition); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); + vec3 specularLight = spec * specularColor * lightColor; + + // put it all together. + result *= ambientLightColor + diffuseLight + specularLight; + } + + //finalColor = vec4(textureCoord.x,textureCoord.y,0,1); // for testing texture coordinates + finalColor = vec4(result, diffuseColor.a); +} diff --git a/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.vert b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.vert new file mode 100644 index 000000000..0a226ecba --- /dev/null +++ b/src/main/resources/com/marginallyclever/ro3/render/renderpasses/mesh.vert @@ -0,0 +1,25 @@ +#version 330 core + +layout(location = 0) in vec3 aPosition; +layout(location = 1) in vec3 aNormal; +layout(location = 2) in vec4 aColor; +layout(location = 3) in vec2 aTexture; + +uniform mat4 projectionMatrix; +uniform mat4 viewMatrix; +uniform mat4 modelMatrix; + +out vec4 fragmentColor; +out vec3 normalVector; +out vec3 fragmentPosition; +out vec2 textureCoord; + +void main() { + vec4 worldPose = modelMatrix * vec4(aPosition, 1.0); + gl_Position = projectionMatrix * viewMatrix * worldPose; + + fragmentColor = aColor; + normalVector = mat3(transpose(inverse(modelMatrix))) * aNormal; + fragmentPosition = vec3(worldPose); + textureCoord = aTexture; +} diff --git a/src/test/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLTestOrthographic.java b/src/test/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLTestOrthographic.java index c4399dee7..64ae026b3 100644 --- a/src/test/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLTestOrthographic.java +++ b/src/test/java/com/marginallyclever/robotoverlord/renderpanel/OpenGLTestOrthographic.java @@ -284,13 +284,13 @@ private FloatBuffer createColorData() { private void createShaderPrograms(GL3 gl) { System.out.println("Create shader programs"); shaderDefault = new ShaderProgram(gl, - readResource("default_330.vert"), + readResource("mesh.vert"), readResource("givenColor_330.frag")); shaderNoTransform = new ShaderProgram(gl, readResource("noTransform_330.vert"), readResource("givenColor_330.frag")); shaderTransform = new ShaderProgram(gl, - readResource("default_330.vert"), + readResource("mesh.vert"), readResource("givenColor_330.frag")); }