mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +00:00 
			
		
		
		
	Add a monitor renderer using TBOs (#443)
This uses the system described in #409, to render monitors in a more efficient manner. Each monitor is backed by a texture buffer object (TBO) which contains a relatively compact encoding of the terminal state. This is then rendered using a shader, which consumes the TBO and uses it to index into main font texture. As we're transmitting significantly less data to the GPU (only 3 bytes per character), this effectively reduces any update lag to 0. FPS appears to be up by a small fraction (10-15fps on my machine, to ~110), possibly as we're now only drawing a single quad (though doing much more work in the shader). On my laptop, with its Intel integrated graphics card, I'm able to draw 120 full-sized monitors (with an effective resolution of 3972 x 2330) at a consistent 60fps. Updates still cause a slight spike, but we always remain above 30fps - a significant improvement over VBOs, where updates would go off the chart. Many thanks to @Lignum and @Lemmmy for devising this scheme, and helping test and review it! ♥
This commit is contained in:
		| @@ -50,12 +50,12 @@ public final class FixedWidthFontRenderer | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     private static float toGreyscale( double[] rgb ) | ||||
|     public static float toGreyscale( double[] rgb ) | ||||
|     { | ||||
|         return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); | ||||
|     } | ||||
|  | ||||
|     private static int getColour( char c, Colour def ) | ||||
|     public static int getColour( char c, Colour def ) | ||||
|     { | ||||
|         return 15 - Terminal.getColour( c, def ); | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,176 @@ | ||||
| /* | ||||
|  * This file is part of ComputerCraft - http://www.computercraft.info | ||||
|  * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. | ||||
|  * Send enquiries to dratcliffe@gmail.com | ||||
|  */ | ||||
|  | ||||
| package dan200.computercraft.client.render; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.shared.util.Palette; | ||||
| import net.minecraft.client.renderer.OpenGlHelper; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.lwjgl.BufferUtils; | ||||
| import org.lwjgl.opengl.GL11; | ||||
| import org.lwjgl.opengl.GL13; | ||||
| import org.lwjgl.opengl.GL20; | ||||
|  | ||||
| import java.io.BufferedInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.nio.ByteBuffer; | ||||
| import java.nio.FloatBuffer; | ||||
|  | ||||
| class MonitorTextureBufferShader | ||||
| { | ||||
|     static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; | ||||
|  | ||||
|     private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); | ||||
|     private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 ); | ||||
|  | ||||
|     private static int uniformMv; | ||||
|     private static int uniformP; | ||||
|  | ||||
|     private static int uniformFont; | ||||
|     private static int uniformWidth; | ||||
|     private static int uniformHeight; | ||||
|     private static int uniformTbo; | ||||
|     private static int uniformPalette; | ||||
|  | ||||
|     private static boolean initialised; | ||||
|     private static boolean ok; | ||||
|     private static int program; | ||||
|  | ||||
|     static void setupUniform( int width, int height, Palette palette, boolean greyscale ) | ||||
|     { | ||||
|         MATRIX_BUFFER.rewind(); | ||||
|         GL11.glGetFloat( GL11.GL_MODELVIEW_MATRIX, MATRIX_BUFFER ); | ||||
|         MATRIX_BUFFER.rewind(); | ||||
|         OpenGlHelper.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); | ||||
|  | ||||
|         MATRIX_BUFFER.rewind(); | ||||
|         GL11.glGetFloat( GL11.GL_PROJECTION_MATRIX, MATRIX_BUFFER ); | ||||
|         MATRIX_BUFFER.rewind(); | ||||
|         OpenGlHelper.glUniformMatrix4( uniformP, false, MATRIX_BUFFER ); | ||||
|  | ||||
|         OpenGlHelper.glUniform1i( uniformWidth, width ); | ||||
|         OpenGlHelper.glUniform1i( uniformHeight, height ); | ||||
|  | ||||
|         PALETTE_BUFFER.rewind(); | ||||
|         for( int i = 0; i < 16; i++ ) | ||||
|         { | ||||
|             double[] colour = palette.getColour( i ); | ||||
|             if( greyscale ) | ||||
|             { | ||||
|                 float f = FixedWidthFontRenderer.toGreyscale( colour ); | ||||
|                 PALETTE_BUFFER.put( f ).put( f ).put( f ); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 PALETTE_BUFFER.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] ); | ||||
|             } | ||||
|         } | ||||
|         PALETTE_BUFFER.flip(); | ||||
|         OpenGlHelper.glUniform3( uniformPalette, PALETTE_BUFFER ); | ||||
|     } | ||||
|  | ||||
|     static boolean use() | ||||
|     { | ||||
|         if( initialised ) | ||||
|         { | ||||
|             if( ok ) OpenGlHelper.glUseProgram( program ); | ||||
|             return ok; | ||||
|         } | ||||
|  | ||||
|         if( ok = load() ) | ||||
|         { | ||||
|             GL20.glUseProgram( program ); | ||||
|             OpenGlHelper.glUniform1i( uniformFont, 0 ); | ||||
|             OpenGlHelper.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 ); | ||||
|         } | ||||
|  | ||||
|         return ok; | ||||
|     } | ||||
|  | ||||
|     private static boolean load() | ||||
|     { | ||||
|         initialised = true; | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" ); | ||||
|             int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" ); | ||||
|  | ||||
|             program = OpenGlHelper.glCreateProgram(); | ||||
|             OpenGlHelper.glAttachShader( program, vertexShader ); | ||||
|             OpenGlHelper.glAttachShader( program, fragmentShader ); | ||||
|             GL20.glBindAttribLocation( program, 0, "v_pos" ); | ||||
|  | ||||
|             OpenGlHelper.glLinkProgram( program ); | ||||
|             boolean ok = OpenGlHelper.glGetProgrami( program, GL20.GL_LINK_STATUS ) != 0; | ||||
|             String log = OpenGlHelper.glGetProgramInfoLog( program, Short.MAX_VALUE ).trim(); | ||||
|             if( !Strings.isNullOrEmpty( log ) ) | ||||
|             { | ||||
|                 ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log ); | ||||
|             } | ||||
|  | ||||
|             GL20.glDetachShader( program, vertexShader ); | ||||
|             GL20.glDetachShader( program, fragmentShader ); | ||||
|             OpenGlHelper.glDeleteShader( vertexShader ); | ||||
|             OpenGlHelper.glDeleteShader( fragmentShader ); | ||||
|  | ||||
|             if( !ok ) return false; | ||||
|  | ||||
|             uniformMv = getUniformLocation( program, "u_mv" ); | ||||
|             uniformP = getUniformLocation( program, "u_p" ); | ||||
|  | ||||
|             uniformFont = getUniformLocation( program, "u_font" ); | ||||
|             uniformWidth = getUniformLocation( program, "u_width" ); | ||||
|             uniformHeight = getUniformLocation( program, "u_height" ); | ||||
|             uniformTbo = getUniformLocation( program, "u_tbo" ); | ||||
|             uniformPalette = getUniformLocation( program, "u_palette" ); | ||||
|  | ||||
|             ComputerCraft.log.info( "Loaded monitor shader." ); | ||||
|             return true; | ||||
|         } | ||||
|         catch( Exception e ) | ||||
|         { | ||||
|             ComputerCraft.log.error( "Cannot load monitor shaders", e ); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static int loadShader( int kind, String path ) throws IOException | ||||
|     { | ||||
|         InputStream stream = TileEntityMonitorRenderer.class.getClassLoader().getResourceAsStream( path ); | ||||
|         if( stream == null ) throw new IllegalArgumentException( "Cannot find " + path ); | ||||
|         byte[] contents = IOUtils.toByteArray( new BufferedInputStream( stream ) ); | ||||
|         ByteBuffer buffer = BufferUtils.createByteBuffer( contents.length ); | ||||
|         buffer.put( contents ); | ||||
|         buffer.position( 0 ); | ||||
|  | ||||
|         int shader = OpenGlHelper.glCreateShader( kind ); | ||||
|  | ||||
|         OpenGlHelper.glShaderSource( shader, buffer ); | ||||
|         OpenGlHelper.glCompileShader( shader ); | ||||
|  | ||||
|         boolean ok = OpenGlHelper.glGetShaderi( shader, GL20.GL_COMPILE_STATUS ) != 0; | ||||
|         String log = OpenGlHelper.glGetShaderInfoLog( shader, Short.MAX_VALUE ).trim(); | ||||
|         if( !Strings.isNullOrEmpty( log ) ) | ||||
|         { | ||||
|             ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log ); | ||||
|         } | ||||
|  | ||||
|         if( !ok ) throw new IllegalStateException( "Cannot compile shader " + path ); | ||||
|         return shader; | ||||
|     } | ||||
|  | ||||
|     private static int getUniformLocation( int program, String name ) | ||||
|     { | ||||
|         int uniform = OpenGlHelper.glGetUniformLocation( program, name ); | ||||
|         if( uniform == -1 ) throw new IllegalStateException( "Cannot find uniform " + name ); | ||||
|         return uniform; | ||||
|     } | ||||
| } | ||||
| @@ -8,23 +8,28 @@ package dan200.computercraft.client.render; | ||||
| import dan200.computercraft.client.FrameInfo; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.core.terminal.Terminal; | ||||
| import dan200.computercraft.core.terminal.TextBuffer; | ||||
| import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; | ||||
| import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; | ||||
| import dan200.computercraft.shared.peripheral.monitor.TileMonitor; | ||||
| import dan200.computercraft.shared.util.Colour; | ||||
| import dan200.computercraft.shared.util.DirectionUtil; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.renderer.BufferBuilder; | ||||
| import net.minecraft.client.renderer.GlStateManager; | ||||
| import net.minecraft.client.renderer.OpenGlHelper; | ||||
| import net.minecraft.client.renderer.Tessellator; | ||||
| import net.minecraft.client.renderer.*; | ||||
| import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; | ||||
| import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | ||||
| import net.minecraft.client.renderer.vertex.VertexBuffer; | ||||
| import net.minecraft.util.EnumFacing; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import org.lwjgl.opengl.GL11; | ||||
| import org.lwjgl.opengl.GL13; | ||||
| import org.lwjgl.opengl.GL15; | ||||
| import org.lwjgl.opengl.GL31; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import java.nio.ByteBuffer; | ||||
|  | ||||
| import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; | ||||
| import static dan200.computercraft.shared.peripheral.monitor.TileMonitor.RENDER_MARGIN; | ||||
|  | ||||
| public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMonitor> | ||||
| @@ -97,8 +102,8 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon | ||||
|         if( terminal != null ) | ||||
|         { | ||||
|             // Draw a terminal | ||||
|             double xScale = xSize / (terminal.getWidth() * FixedWidthFontRenderer.FONT_WIDTH); | ||||
|             double yScale = ySize / (terminal.getHeight() * FixedWidthFontRenderer.FONT_HEIGHT); | ||||
|             double xScale = xSize / (terminal.getWidth() * FONT_WIDTH); | ||||
|             double yScale = ySize / (terminal.getHeight() * FONT_HEIGHT); | ||||
|  | ||||
|             GlStateManager.pushMatrix(); | ||||
|             GlStateManager.scale( (float) xScale, (float) -yScale, 1.0f ); | ||||
| @@ -147,6 +152,52 @@ public class TileEntityMonitorRenderer extends TileEntitySpecialRenderer<TileMon | ||||
|  | ||||
|         switch( renderer ) | ||||
|         { | ||||
|             case TBO: | ||||
|             { | ||||
|                 if( !MonitorTextureBufferShader.use() ) return; | ||||
|  | ||||
|                 Terminal terminal = monitor.getTerminal(); | ||||
|                 int width = terminal.getWidth(), height = terminal.getHeight(); | ||||
|                 int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; | ||||
|  | ||||
|                 if( redraw ) | ||||
|                 { | ||||
|                     ByteBuffer monitorBuffer = GLAllocation.createDirectByteBuffer( width * height * 3 ); | ||||
|                     for( int y = 0; y < height; y++ ) | ||||
|                     { | ||||
|                         TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y ); | ||||
|                         for( int x = 0; x < width; x++ ) | ||||
|                         { | ||||
|                             monitorBuffer.put( (byte) (text.charAt( x ) & 0xFF) ); | ||||
|                             monitorBuffer.put( (byte) getColour( textColour.charAt( x ), Colour.White ) ); | ||||
|                             monitorBuffer.put( (byte) getColour( background.charAt( x ), Colour.Black ) ); | ||||
|                         } | ||||
|                     } | ||||
|                     monitorBuffer.flip(); | ||||
|  | ||||
|                     OpenGlHelper.glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer ); | ||||
|                     OpenGlHelper.glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL15.GL_STATIC_DRAW ); | ||||
|                     OpenGlHelper.glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 ); | ||||
|                 } | ||||
|  | ||||
|                 // Bind TBO texture and set up the uniforms. We've already set up the main font above. | ||||
|                 GlStateManager.setActiveTexture( MonitorTextureBufferShader.TEXTURE_INDEX ); | ||||
|                 GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture ); | ||||
|                 GlStateManager.setActiveTexture( GL13.GL_TEXTURE0 ); | ||||
|  | ||||
|                 MonitorTextureBufferShader.setupUniform( width, height, terminal.getPalette(), !monitor.isColour() ); | ||||
|  | ||||
|                 buffer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION ); | ||||
|                 buffer.pos( -xMargin, -yMargin, 0 ).endVertex(); | ||||
|                 buffer.pos( -xMargin, pixelHeight + yMargin, 0 ).endVertex(); | ||||
|                 buffer.pos( pixelWidth + xMargin, -yMargin, 0 ).endVertex(); | ||||
|                 buffer.pos( pixelWidth + xMargin, pixelHeight + yMargin, 0 ).endVertex(); | ||||
|                 tessellator.draw(); | ||||
|  | ||||
|                 OpenGlHelper.glUseProgram( 0 ); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             case VBO: | ||||
|             { | ||||
|                 VertexBuffer vbo = monitor.buffer; | ||||
|   | ||||
| @@ -8,10 +8,16 @@ package dan200.computercraft.shared.peripheral.monitor; | ||||
| import dan200.computercraft.client.gui.FixedWidthFontRenderer; | ||||
| import dan200.computercraft.shared.common.ClientTerminal; | ||||
| import net.minecraft.client.renderer.GLAllocation; | ||||
| import net.minecraft.client.renderer.GlStateManager; | ||||
| import net.minecraft.client.renderer.OpenGlHelper; | ||||
| import net.minecraft.client.renderer.vertex.VertexBuffer; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraftforge.fml.relauncher.Side; | ||||
| import net.minecraftforge.fml.relauncher.SideOnly; | ||||
| import org.lwjgl.opengl.GL11; | ||||
| import org.lwjgl.opengl.GL15; | ||||
| import org.lwjgl.opengl.GL30; | ||||
| import org.lwjgl.opengl.GL31; | ||||
|  | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| @@ -26,6 +32,8 @@ public final class ClientMonitor extends ClientTerminal | ||||
|     public long lastRenderFrame = -1; | ||||
|     public BlockPos lastRenderPos = null; | ||||
|  | ||||
|     public int tboBuffer; | ||||
|     public int tboTexture; | ||||
|     public VertexBuffer buffer; | ||||
|     public int displayList = 0; | ||||
|  | ||||
| @@ -43,7 +51,7 @@ public final class ClientMonitor extends ClientTerminal | ||||
|     /** | ||||
|      * Create the appropriate buffer if needed. | ||||
|      * | ||||
|      * @param renderer The renderer to use. This can be fetched from {@link #renderer()}. | ||||
|      * @param renderer The renderer to use. This can be fetched from {@link MonitorRenderer#current()}. | ||||
|      * @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer, | ||||
|      * or this mode does not require one. | ||||
|      */ | ||||
| @@ -52,6 +60,26 @@ public final class ClientMonitor extends ClientTerminal | ||||
|     { | ||||
|         switch( renderer ) | ||||
|         { | ||||
|             case TBO: | ||||
|             { | ||||
|                 if( tboBuffer != 0 ) return false; | ||||
|  | ||||
|                 deleteBuffers(); | ||||
|  | ||||
|                 tboBuffer = OpenGlHelper.glGenBuffers(); | ||||
|                 OpenGlHelper.glBindBuffer( GL31.GL_TEXTURE_BUFFER, tboBuffer ); | ||||
|                 GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW ); | ||||
|                 tboTexture = GlStateManager.generateTexture(); | ||||
|                 GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture ); | ||||
|                 GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8, tboBuffer ); | ||||
|                 GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 ); | ||||
|  | ||||
|                 OpenGlHelper.glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 ); | ||||
|  | ||||
|                 addMonitor(); | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             case VBO: | ||||
|                 if( buffer != null ) return false; | ||||
|  | ||||
| @@ -59,6 +87,7 @@ public final class ClientMonitor extends ClientTerminal | ||||
|                 buffer = new VertexBuffer( FixedWidthFontRenderer.POSITION_COLOR_TEX ); | ||||
|                 addMonitor(); | ||||
|                 return true; | ||||
|  | ||||
|             case DISPLAY_LIST: | ||||
|                 if( displayList != 0 ) return false; | ||||
|  | ||||
| @@ -82,6 +111,19 @@ public final class ClientMonitor extends ClientTerminal | ||||
|  | ||||
|     private void deleteBuffers() | ||||
|     { | ||||
|  | ||||
|         if( tboBuffer != 0 ) | ||||
|         { | ||||
|             OpenGlHelper.glDeleteBuffers( tboBuffer ); | ||||
|             tboBuffer = 0; | ||||
|         } | ||||
|  | ||||
|         if( tboTexture != 0 ) | ||||
|         { | ||||
|             GlStateManager.deleteTexture( tboTexture ); | ||||
|             tboTexture = 0; | ||||
|         } | ||||
|  | ||||
|         if( buffer != null ) | ||||
|         { | ||||
|             buffer.deleteGlBuffers(); | ||||
| @@ -98,7 +140,7 @@ public final class ClientMonitor extends ClientTerminal | ||||
|     @SideOnly( Side.CLIENT ) | ||||
|     public void destroy() | ||||
|     { | ||||
|         if( buffer != null || displayList != 0 ) | ||||
|         if( tboBuffer != 0 || buffer != null || displayList != 0 ) | ||||
|         { | ||||
|             synchronized( allMonitors ) | ||||
|             { | ||||
|   | ||||
| @@ -9,6 +9,7 @@ package dan200.computercraft.shared.peripheral.monitor; | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.client.render.TileEntityMonitorRenderer; | ||||
| import net.minecraft.client.renderer.OpenGlHelper; | ||||
| import org.lwjgl.opengl.GLContext; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import java.util.Locale; | ||||
| @@ -27,7 +28,14 @@ public enum MonitorRenderer | ||||
|     BEST, | ||||
|  | ||||
|     /** | ||||
|      * Render using VBOs. This is the default when supported. | ||||
|      * Render using texture buffer objects. | ||||
|      * | ||||
|      * @see org.lwjgl.opengl.GL31#glTexBuffer(int, int, int) | ||||
|      */ | ||||
|     TBO, | ||||
|  | ||||
|     /** | ||||
|      * Render using VBOs. | ||||
|      * | ||||
|      * @see net.minecraft.client.renderer.vertex.VertexBuffer | ||||
|      */ | ||||
| @@ -84,6 +92,16 @@ public enum MonitorRenderer | ||||
|         { | ||||
|             case BEST: | ||||
|                 return best(); | ||||
|             case TBO: | ||||
|                 checkCapabilities(); | ||||
|                 if( !textureBuffer ) | ||||
|                 { | ||||
|                     ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." ); | ||||
|                     ComputerCraft.monitorRenderer = BEST; | ||||
|                     return best(); | ||||
|                 } | ||||
|  | ||||
|                 return TBO; | ||||
|             case VBO: | ||||
|                 if( !OpenGlHelper.vboSupported ) | ||||
|                 { | ||||
| @@ -100,6 +118,20 @@ public enum MonitorRenderer | ||||
|  | ||||
|     private static MonitorRenderer best() | ||||
|     { | ||||
|         return OpenGlHelper.vboSupported ? VBO : DISPLAY_LIST; | ||||
|         checkCapabilities(); | ||||
|         if( textureBuffer ) return TBO; | ||||
|         if( OpenGlHelper.vboSupported ) return VBO; | ||||
|         return DISPLAY_LIST; | ||||
|     } | ||||
|  | ||||
|     private static boolean initialised = false; | ||||
|     private static boolean textureBuffer = false; | ||||
|  | ||||
|     private static void checkCapabilities() | ||||
|     { | ||||
|         if( initialised ) return; | ||||
|  | ||||
|         textureBuffer = GLContext.getCapabilities().OpenGL31; | ||||
|         initialised = true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -187,6 +187,7 @@ gui.computercraft:config.peripheral.modem_high_altitude_range_during_storm=Modem | ||||
| gui.computercraft:config.peripheral.max_notes_per_tick=Maximum notes that a computer can play at once | ||||
| gui.computercraft:config.peripheral.monitor_renderer=Monitor renderer | ||||
| gui.computercraft:config.peripheral.monitor_renderer.best=Best | ||||
| gui.computercraft:config.peripheral.monitor_renderer.tbo=Texture Buffers | ||||
| gui.computercraft:config.peripheral.monitor_renderer.vbo=Vertex Buffers | ||||
| gui.computercraft:config.peripheral.monitor_renderer.display_list=Display Lists | ||||
|  | ||||
|   | ||||
							
								
								
									
										40
									
								
								src/main/resources/assets/computercraft/shaders/monitor.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/main/resources/assets/computercraft/shaders/monitor.frag
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| #version 140 | ||||
|  | ||||
| #define FONT_WIDTH 6.0 | ||||
| #define FONT_HEIGHT 9.0 | ||||
|  | ||||
| uniform sampler2D u_font; | ||||
| uniform int u_width; | ||||
| uniform int u_height; | ||||
| uniform samplerBuffer u_tbo; | ||||
| uniform vec3 u_palette[16]; | ||||
|  | ||||
| in vec2 f_pos; | ||||
|  | ||||
| out vec4 colour; | ||||
|  | ||||
| vec2 texture_corner(int index) { | ||||
|     float x = 1.0 + float(index % 16) * (FONT_WIDTH + 2.0); | ||||
|     float y = 1.0 + float(index / 16) * (FONT_HEIGHT + 2.0); | ||||
|     return vec2(x, y); | ||||
| } | ||||
|  | ||||
| void main() { | ||||
|     vec2 term_pos = vec2(f_pos.x / FONT_WIDTH, f_pos.y / FONT_HEIGHT); | ||||
|     vec2 corner = floor(term_pos); | ||||
|  | ||||
|     ivec2 cell = ivec2(corner); | ||||
|     int index = 3 * (clamp(cell.x, 0, u_width - 1) + clamp(cell.y, 0, u_height - 1) * u_width); | ||||
|  | ||||
|     // 1 if 0 <= x, y < width, height, 0 otherwise | ||||
|     vec2 outside = step(vec2(0.0, 0.0), vec2(cell)) * step(vec2(cell), vec2(float(u_width) - 1.0, float(u_height) - 1.0)); | ||||
|     float mult = outside.x * outside.y; | ||||
|  | ||||
|     int character = int(texelFetch(u_tbo, index).r * 255.0); | ||||
|     int fg = int(texelFetch(u_tbo, index + 1).r * 255.0); | ||||
|     int bg = int(texelFetch(u_tbo, index + 2).r * 255.0); | ||||
|  | ||||
|     vec2 pos = (term_pos - corner) * vec2(FONT_WIDTH, FONT_HEIGHT); | ||||
|     vec4 img = texture2D(u_font, (texture_corner(character) + pos) / 256.0); | ||||
|     colour = vec4(mix(u_palette[bg], img.rgb * u_palette[fg], img.a * mult), 1.0); | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/main/resources/assets/computercraft/shaders/monitor.vert
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main/resources/assets/computercraft/shaders/monitor.vert
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #version 140 | ||||
|  | ||||
| uniform mat4 u_mv; | ||||
| uniform mat4 u_p; | ||||
|  | ||||
| in vec3 v_pos; | ||||
|  | ||||
| out vec2 f_pos; | ||||
|  | ||||
| void main() { | ||||
|     gl_Position = u_p * u_mv * vec4(v_pos.x, v_pos.y, 0, 1); | ||||
|     f_pos = v_pos.xy; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates