Add GPU renderer

This commit is contained in:
Adam
2018-11-15 09:19:37 -05:00
parent 3c84d98638
commit 3f5e273349
74 changed files with 6201 additions and 22 deletions

View File

@@ -29,4 +29,9 @@ package net.runelite.api;
*/
public interface BufferProvider
{
int[] getPixels();
int getWidth();
int getHeight();
}

View File

@@ -34,6 +34,7 @@ import net.runelite.api.annotations.VisibleForDevtools;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.hooks.Callbacks;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.vars.AccountType;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
@@ -50,6 +51,10 @@ public interface Client extends GameEngine
*/
Callbacks getCallbacks();
DrawCallbacks getDrawCallbacks();
void setDrawCallbacks(DrawCallbacks drawCallbacks);
/**
* Retrieve a global logger for the client.
* This is most useful for mixins which can't have their own.
@@ -210,6 +215,18 @@ public interface Client extends GameEngine
*/
int getWorld();
/**
* Gets the canvas height
* @return
*/
int getCanvasHeight();
/**
* Gets the canvas width
* @return
*/
int getCanvasWidth();
/**
* Gets the height of the viewport.
*
@@ -1485,6 +1502,13 @@ public interface Client extends GameEngine
*/
EnumSet<WorldType> getWorldType();
/**
* Gets the enabled state for the Oculus orb mode
*
* @return
*/
int getOculusOrbState();
/**
* Sets the enabled state for the Oculus orb state
*
@@ -1509,4 +1533,29 @@ public interface Client extends GameEngine
* @param world target world to hop to
*/
void hopToWorld(World world);
boolean isGpu();
void setGpu(boolean gpu);
int get3dZoom();
int getCenterX();
int getCenterY();
int getCameraX2();
int getCameraY2();
int getCameraZ2();
TextureProvider getTextureProvider();
NodeCache getCachedModels2();
void setRenderArea(boolean[][] renderArea);
int getRasterizer3D_clipMidX2();
int getRasterizer3D_clipNegativeMidX();
int getRasterizer3D_clipNegativeMidY();
int getRasterizer3D_clipMidY2();
void checkClickbox(Model model, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
}

View File

@@ -67,4 +67,6 @@ public class Constants
* the plane value to 0-3.
*/
public static final int MAX_Z = 4;
public static final int TILE_FLAG_BRIDGE = 2;
}

View File

@@ -38,4 +38,7 @@ public interface DecorativeObject extends TileObject
* @see net.runelite.api.model.Jarvis
*/
Polygon getConvexHull();
Renderable getRenderable();
Renderable getRenderable2();
}

View File

@@ -51,4 +51,6 @@ public interface GameEngine
* @return true if on the main thread, false otherwise
*/
boolean isClientThread();
void resizeCanvas();
}

View File

@@ -67,4 +67,6 @@ public interface GameObject extends TileObject
* @return the orientation
*/
Angle getOrientation();
Renderable getRenderable();
}

View File

@@ -29,4 +29,5 @@ package net.runelite.api;
*/
public interface GroundObject extends TileObject
{
Renderable getRenderable();
}

View File

@@ -46,4 +46,61 @@ public interface Model extends Renderable
* @return the triangle
*/
List<Triangle> getTriangles();
int getVerticesCount();
int[] getVerticesX();
int[] getVerticesY();
int[] getVerticesZ();
int getTrianglesCount();
int[] getTrianglesX();
int[] getTrianglesY();
int[] getTrianglesZ();
int[] getFaceColors1();
int[] getFaceColors2();
int[] getFaceColors3();
byte[] getTriangleTransparencies();
int getSceneId();
void setSceneId(int sceneId);
int getBufferOffset();
void setBufferOffset(int bufferOffset);
int getUvBufferOffset();
void setUvBufferOffset(int bufferOffset);
int getModelHeight();
void calculateBoundsCylinder();
byte[] getFaceRenderPriorities();
int getRadius();
short[] getFaceTextures();
float[][] getFaceTextureUCoordinates();
float[][] getFaceTextureVCoordinates();
void calculateExtreme(int orientation);
int getCenterX();
int getCenterY();
int getCenterZ();
int getExtremeX();
int getExtremeY();
int getExtremeZ();
int getXYZMag();
}

View File

@@ -33,4 +33,8 @@ public interface NodeCache
* Resets cache.
*/
void reset();
void setCapacity(int capacity);
void setRemainingCapacity(int remainingCapacity);
}

View File

@@ -36,6 +36,7 @@ import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static net.runelite.api.Constants.TILE_FLAG_BRIDGE;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Triangle;
@@ -56,8 +57,6 @@ public class Perspective
public static final int SCENE_SIZE = Constants.SCENE_SIZE; // in tiles
private static final int TILE_FLAG_BRIDGE = 2;
public static final int[] SINE = new int[2048]; // sine angles for each of the 2048 units, * 65536 and stored as an int
public static final int[] COSINE = new int[2048]; // cosine

View File

@@ -35,4 +35,8 @@ public interface Renderable extends Node
* @return the model
*/
Model getModel();
void setModelHeight(int modelHeight);
void draw(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
}

View File

@@ -35,4 +35,7 @@ public interface Scene
* @return the tiles in [plane][x][y]
*/
Tile[][][] getTiles();
int getDrawDistance();
void setDrawDistance(int drawDistance);
}

View File

@@ -56,4 +56,33 @@ public interface SceneTileModel
* @return the rotation
*/
int getRotation();
int[] getFaceX();
int[] getFaceY();
int[] getFaceZ();
int[] getVertexX();
int[] getVertexY();
int[] getVertexZ();
int[] getTriangleColorA();
int[] getTriangleColorB();
int[] getTriangleColorC();
int[] getTriangleTextureId();
int getBufferOffset();
void setBufferOffset(int bufferOffset);
int getUvBufferOffset();
void setUvBufferOffset(int bufferOffset);
int getBufferLen();
void setBufferLen(int bufferLen);
}

View File

@@ -35,4 +35,23 @@ public interface SceneTilePaint
* @return the paint RGB
*/
int getRBG();
int getSwColor();
int getSeColor();
int getNwColor();
int getNeColor();
int getTexture();
int getBufferOffset();
void setBufferOffset(int bufferOffset);
int getUvBufferOffset();
void setUvBufferOffset(int bufferOffset);
int getBufferLen();
void setBufferLen(int bufferLen);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.api;
public interface Texture extends Node
{
int[] getPixels();
int getAnimationDirection();
int getAnimationSpeed();
boolean isLoaded();
float getU();
void setU(float u);
float getV();
void setV(float v);
}

View File

@@ -26,5 +26,25 @@ package net.runelite.api;
public interface TextureProvider
{
void checkTextures(int var1);
double getBrightness();
/**
* Set the brightness for textures, clearing the texture cache.
* @param brightness
*/
void setBrightness(double brightness);
/**
* Get all textures
*
* @return
*/
Texture[] getTextures();
/**
* Get the pixels for a texture
* @param textureId
* @return
*/
int[] load(int textureId);
}

View File

@@ -110,6 +110,13 @@ public interface Tile
*/
int getPlane();
/**
* Get the plane this tile is rendered on, which is where the tile heights are from.
*
* @return
*/
int getRenderLevel();
/**
* Computes and returns whether this tile has line of sight to another.
*
@@ -124,4 +131,11 @@ public interface Tile
* @return the ground items
*/
List<Item> getGroundItems();
/**
* Return the tile under this one, if this tile is a bridge
*
* @return
*/
Tile getBridge();
}

View File

@@ -49,4 +49,7 @@ public interface WallObject extends TileObject
* @return the boundary configuration
*/
int getConfig();
Renderable getRenderable1();
Renderable getRenderable2();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.api.hooks;
import net.runelite.api.Renderable;
import net.runelite.api.SceneTileModel;
import net.runelite.api.SceneTilePaint;
import net.runelite.api.Texture;
public interface DrawCallbacks
{
void draw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
void drawScenePaint(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z,
SceneTilePaint paint, int tileZ, int tileX, int tileY,
int zoom, int centerX, int centerY);
void drawSceneModel(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z,
SceneTileModel model, int tileZ, int tileX, int tileY,
int zoom, int centerX, int centerY);
void draw();
void drawScene(int cameraX, int cameraY, int cameraZ, int cameraPitch, int cameraYaw, int plane);
void animate(Texture texture, int diff);
}

View File

@@ -37,6 +37,7 @@
<properties>
<guice.version>4.1.0</guice.version>
<jogl.version>2.3.2</jogl.version>
<jarsigner.skip>true</jarsigner.skip>
</properties>
@@ -90,6 +91,45 @@
<artifactId>commons-text</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>${jogl.version}</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>${jogl.version}</version>
<classifier>natives-windows-amd64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>${jogl.version}</version>
<classifier>natives-windows-i586</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
<version>${jogl.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
<version>${jogl.version}</version>
<classifier>natives-windows-amd64</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt</artifactId>
<version>${jogl.version}</version>
<classifier>natives-windows-i586</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.runelite</groupId>
@@ -230,6 +270,18 @@
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.jogamp.jogl:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
<filter>
<artifact>org.jogamp.gluegen:*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

View File

@@ -41,12 +41,15 @@ import java.awt.image.VolatileImage;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.BufferProvider;
import net.runelite.api.Client;
import net.runelite.api.MainBufferProvider;
import net.runelite.api.RenderOverview;
import net.runelite.api.Renderable;
import net.runelite.api.WorldMapManager;
import net.runelite.api.events.GameTick;
import net.runelite.api.hooks.Callbacks;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.widgets.Widget;
import static net.runelite.api.widgets.WidgetInfo.WORLD_MAP_VIEW;
import net.runelite.client.Notifier;
@@ -300,6 +303,15 @@ public class Hooks implements Callbacks
// Draw clientUI overlays
clientUi.paintOverlays(graphics2d);
graphics2d.dispose();
if (client.isGpu())
{
// processDrawComplete gets called on GPU by the gpu plugin at the end of its
// drawing cycle, which is later on.
return;
}
// Stretch the game image if the user has that enabled
if (client.isStretchedEnabled())
{
@@ -418,4 +430,36 @@ public class Hooks implements Callbacks
// have been processed is typically more useful.
shouldProcessGameTick = true;
}
public static void renderDraw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash)
{
DrawCallbacks drawCallbacks = client.getDrawCallbacks();
if (drawCallbacks != null)
{
drawCallbacks.draw(renderable, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
}
else
{
renderable.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
}
}
public static void clearColorBuffer(int x, int y, int width, int height, int color)
{
BufferProvider bp = client.getBufferProvider();
int canvasWidth = bp.getWidth();
int[] pixels = bp.getPixels();
int pixelPos = y * canvasWidth + x;
int pixelJump = canvasWidth - width;
for (int cy = y; cy < y + height; cy++)
{
for (int cx = x; cx < x + width; cx++)
{
pixels[pixelPos++] = 0;
}
pixelPos += pixelJump;
}
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import com.jogamp.opengl.GL4;
import java.io.InputStream;
import java.util.Scanner;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class GLUtil
{
private static final int ERR_LEN = 1024;
private static final int[] buf = new int[1];
static int glGetInteger(GL4 gl, int pname)
{
gl.glGetIntegerv(pname, buf, 0);
return buf[0];
}
static int glGetShader(GL4 gl, int shader, int pname)
{
gl.glGetShaderiv(shader, pname, buf, 0);
assert buf[0] > -1;
return buf[0];
}
static int glGetProgram(GL4 gl, int program, int pname)
{
gl.glGetProgramiv(program, pname, buf, 0);
assert buf[0] > -1;
return buf[0];
}
static String glGetShaderInfoLog(GL4 gl, int shader)
{
byte[] err = new byte[ERR_LEN];
gl.glGetShaderInfoLog(shader, ERR_LEN, buf, 0, err, 0);
return new String(err);
}
static String glGetProgramInfoLog(GL4 gl, int program)
{
byte[] err = new byte[ERR_LEN];
gl.glGetProgramInfoLog(program, ERR_LEN, buf, 0, err, 0);
return new String(err);
}
static int glGenVertexArrays(GL4 gl)
{
gl.glGenVertexArrays(1, buf, 0);
return buf[0];
}
static void glDeleteVertexArrays(GL4 gl, int vertexArray)
{
buf[0] = vertexArray;
gl.glDeleteVertexArrays(1, buf, 0);
}
static int glGenBuffers(GL4 gl)
{
gl.glGenBuffers(1, buf, 0);
return buf[0];
}
static void glDeleteBuffer(GL4 gl, int buffer)
{
buf[0] = buffer;
gl.glDeleteBuffers(1, buf, 0);
}
static int glGenTexture(GL4 gl)
{
gl.glGenTextures(1, buf, 0);
return buf[0];
}
static void glDeleteTexture(GL4 gl, int texture)
{
buf[0] = texture;
gl.glDeleteTextures(1, buf, 0);
}
static void loadShaders(GL4 gl, int glProgram, int glVertexShader, int glGeometryShader, int glFragmentShader,
String vertexShaderStr, String geomShaderStr, String fragShaderStr) throws ShaderException
{
compileAndAttach(gl, glProgram, glVertexShader, vertexShaderStr);
if (glGeometryShader != -1)
{
compileAndAttach(gl, glProgram, glGeometryShader, geomShaderStr);
}
compileAndAttach(gl, glProgram, glFragmentShader, fragShaderStr);
gl.glLinkProgram(glProgram);
if (glGetProgram(gl, glProgram, gl.GL_LINK_STATUS) == gl.GL_FALSE)
{
String err = glGetProgramInfoLog(gl, glProgram);
throw new ShaderException(err);
}
gl.glValidateProgram(glProgram);
if (glGetProgram(gl, glProgram, gl.GL_VALIDATE_STATUS) == gl.GL_FALSE)
{
String err = glGetProgramInfoLog(gl, glProgram);
throw new ShaderException(err);
}
}
static void loadComputeShader(GL4 gl, int glProgram, int glComputeShader, String str) throws ShaderException
{
compileAndAttach(gl, glProgram, glComputeShader, str);
gl.glLinkProgram(glProgram);
if (glGetProgram(gl, glProgram, gl.GL_LINK_STATUS) == gl.GL_FALSE)
{
String err = glGetProgramInfoLog(gl, glProgram);
throw new ShaderException(err);
}
gl.glValidateProgram(glProgram);
if (glGetProgram(gl, glProgram, gl.GL_VALIDATE_STATUS) == gl.GL_FALSE)
{
String err = glGetProgramInfoLog(gl, glProgram);
throw new ShaderException(err);
}
}
private static void compileAndAttach(GL4 gl, int program, int shader, String source) throws ShaderException
{
gl.glShaderSource(shader, 1, new String[]{source}, null);
gl.glCompileShader(shader);
if (glGetShader(gl, shader, gl.GL_COMPILE_STATUS) == gl.GL_TRUE)
{
gl.glAttachShader(program, shader);
}
else
{
String err = glGetShaderInfoLog(gl, shader);
throw new ShaderException(err);
}
}
static String inputStreamToString(InputStream in)
{
Scanner scanner = new Scanner(in).useDelimiter("\\A");
return scanner.next();
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
class GpuFloatBuffer
{
private FloatBuffer buffer = allocateDirect(65536);
void put(float texture, float u, float v, float pad)
{
buffer.put(texture).put(u).put(v).put(pad);
}
void flip()
{
buffer.flip();
}
void clear()
{
buffer.clear();
}
void ensureCapacity(int size)
{
while (buffer.remaining() < size)
{
FloatBuffer newB = allocateDirect(buffer.capacity() * 2);
buffer.flip();
newB.put(buffer);
buffer = newB;
}
}
FloatBuffer getBuffer()
{
return buffer;
}
static FloatBuffer allocateDirect(int size)
{
return ByteBuffer.allocateDirect(size * Float.BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
class GpuIntBuffer
{
private IntBuffer buffer = allocateDirect(65536);
void put(int x, int y, int z)
{
buffer.put(x).put(y).put(z);
}
void put(int x, int y, int z, int c)
{
buffer.put(x).put(y).put(z).put(c);
}
void flip()
{
buffer.flip();
}
void clear()
{
buffer.clear();
}
void ensureCapacity(int size)
{
while (buffer.remaining() < size)
{
IntBuffer newB = allocateDirect(buffer.capacity() * 2);
buffer.flip();
newB.put(buffer);
buffer = newB;
}
}
IntBuffer getBuffer()
{
return buffer;
}
static IntBuffer allocateDirect(int size)
{
return ByteBuffer.allocateDirect(size * Integer.BYTES)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("gpu")
public interface GpuPluginConfig extends Config
{
@ConfigItem(
keyName = "drawDistance",
name = "Draw Distance",
description = "Draw distance"
)
default int drawDistance()
{
return 25;
}
}

View File

@@ -0,0 +1,549 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject;
import net.runelite.api.GroundObject;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.Renderable;
import net.runelite.api.Scene;
import net.runelite.api.SceneTileModel;
import net.runelite.api.SceneTilePaint;
import net.runelite.api.Tile;
import net.runelite.api.WallObject;
@Singleton
class SceneUploader
{
@Inject
private Client client;
int sceneId = (int) (System.currentTimeMillis() / 1000L);
private int offset;
private int uvoffset;
void upload(Scene scene, GpuIntBuffer vertexbuffer, GpuFloatBuffer uvBuffer)
{
++sceneId;
offset = 0;
uvoffset = 0;
vertexbuffer.clear();
uvBuffer.clear();
for (int z = 0; z < Constants.MAX_Z; ++z)
{
for (int x = 0; x < Constants.SCENE_SIZE; ++x)
{
for (int y = 0; y < Constants.SCENE_SIZE; ++y)
{
Tile tile = scene.getTiles()[z][x][y];
if (tile != null)
{
reset(tile);
}
}
}
}
for (int z = 0; z < Constants.MAX_Z; ++z)
{
for (int x = 0; x < Constants.SCENE_SIZE; ++x)
{
for (int y = 0; y < Constants.SCENE_SIZE; ++y)
{
Tile tile = scene.getTiles()[z][x][y];
if (tile != null)
{
upload(tile, vertexbuffer, uvBuffer);
}
}
}
}
}
private void reset(Tile tile)
{
Tile bridge = tile.getBridge();
if (bridge != null)
{
reset(bridge);
}
SceneTilePaint sceneTilePaint = tile.getSceneTilePaint();
if (sceneTilePaint != null)
{
sceneTilePaint.setBufferOffset(-1);
}
SceneTileModel sceneTileModel = tile.getSceneTileModel();
if (sceneTileModel != null)
{
sceneTileModel.setBufferOffset(-1);
}
WallObject wallObject = tile.getWallObject();
if (wallObject != null)
{
if (wallObject.getRenderable1() instanceof Model)
{
((Model) wallObject.getRenderable1()).setBufferOffset(-1);
}
if (wallObject.getRenderable2() instanceof Model)
{
((Model) wallObject.getRenderable2()).setBufferOffset(-1);
}
}
GroundObject groundObject = tile.getGroundObject();
if (groundObject != null)
{
if (groundObject.getRenderable() instanceof Model)
{
((Model) groundObject.getRenderable()).setBufferOffset(-1);
}
}
DecorativeObject decorativeObject = tile.getDecorativeObject();
if (decorativeObject != null)
{
if (decorativeObject.getRenderable() instanceof Model)
{
((Model) decorativeObject.getRenderable()).setBufferOffset(-1);
}
}
GameObject[] gameObjects = tile.getGameObjects();
for (GameObject gameObject : gameObjects)
{
if (gameObject == null)
{
continue;
}
if (gameObject.getRenderable() instanceof Model)
{
((Model) gameObject.getRenderable()).setBufferOffset(-1);
}
}
}
private void upload(Tile tile, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
{
Tile bridge = tile.getBridge();
if (bridge != null)
{
upload(bridge, vertexBuffer, uvBuffer);
}
SceneTilePaint sceneTilePaint = tile.getSceneTilePaint();
if (sceneTilePaint != null)
{
sceneTilePaint.setBufferOffset(offset);
if (sceneTilePaint.getTexture() != -1)
{
sceneTilePaint.setUvBufferOffset(uvoffset);
}
else
{
sceneTilePaint.setUvBufferOffset(-1);
}
Point tilePoint = tile.getSceneLocation();
int len = upload(sceneTilePaint, tile.getRenderLevel(), tilePoint.getX(), tilePoint.getY(), vertexBuffer, uvBuffer);
sceneTilePaint.setBufferLen(len);
offset += len;
if (sceneTilePaint.getTexture() != -1)
{
uvoffset += len;
}
}
SceneTileModel sceneTileModel = tile.getSceneTileModel();
if (sceneTileModel != null)
{
sceneTileModel.setBufferOffset(offset);
if (sceneTileModel.getTriangleTextureId() != null)
{
sceneTileModel.setUvBufferOffset(uvoffset);
}
else
{
sceneTileModel.setUvBufferOffset(-1);
}
Point tilePoint = tile.getSceneLocation();
int len = upload(sceneTileModel, tilePoint.getX(), tilePoint.getY(), vertexBuffer, uvBuffer);
sceneTileModel.setBufferLen(len);
offset += len;
if (sceneTileModel.getTriangleTextureId() != null)
{
uvoffset += len;
}
}
WallObject wallObject = tile.getWallObject();
if (wallObject != null)
{
Renderable renderable1 = wallObject.getRenderable1();
if (renderable1 instanceof Model)
{
uploadModel((Model) renderable1, vertexBuffer, uvBuffer);
}
Renderable renderable2 = wallObject.getRenderable2();
if (renderable2 instanceof Model)
{
uploadModel((Model) renderable2, vertexBuffer, uvBuffer);
}
}
GroundObject groundObject = tile.getGroundObject();
if (groundObject != null)
{
Renderable renderable = groundObject.getRenderable();
if (renderable instanceof Model)
{
uploadModel((Model) renderable, vertexBuffer, uvBuffer);
}
}
DecorativeObject decorativeObject = tile.getDecorativeObject();
if (decorativeObject != null)
{
Renderable renderable = decorativeObject.getRenderable();
if (renderable instanceof Model)
{
uploadModel((Model) renderable, vertexBuffer, uvBuffer);
}
Renderable renderable2 = decorativeObject.getRenderable2();
if (renderable2 instanceof Model)
{
uploadModel((Model) renderable2, vertexBuffer, uvBuffer);
}
}
GameObject[] gameObjects = tile.getGameObjects();
for (GameObject gameObject : gameObjects)
{
if (gameObject == null)
{
continue;
}
Renderable renderable = gameObject.getRenderable();
if (renderable instanceof Model)
{
uploadModel((Model) gameObject.getRenderable(), vertexBuffer, uvBuffer);
}
}
}
private int upload(SceneTilePaint tile, int tileZ, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
{
final int[][][] tileHeights = client.getTileHeights();
final int localX = 0;
final int localY = 0;
int swHeight = tileHeights[tileZ][tileX][tileY];
int seHeight = tileHeights[tileZ][tileX + 1][tileY];
int neHeight = tileHeights[tileZ][tileX + 1][tileY + 1];
int nwHeight = tileHeights[tileZ][tileX][tileY + 1];
final int neColor = tile.getNeColor();
final int nwColor = tile.getNwColor();
final int seColor = tile.getSeColor();
final int swColor = tile.getSwColor();
if (neColor == 12345678)
{
return 0;
}
vertexBuffer.ensureCapacity(24);
uvBuffer.ensureCapacity(24);
// 0,0
int vertexDx = localX;
int vertexDy = localY;
int vertexDz = swHeight;
final int c1 = swColor;
// 1,0
int vertexCx = localX + Perspective.LOCAL_TILE_SIZE;
int vertexCy = localY;
int vertexCz = seHeight;
final int c2 = nwColor;
// 1,1
int vertexAx = localX + Perspective.LOCAL_TILE_SIZE;
int vertexAy = localY + Perspective.LOCAL_TILE_SIZE;
int vertexAz = neHeight;
final int c3 = neColor;
// 0,1
int vertexBx = localX;
int vertexBy = localY + Perspective.LOCAL_TILE_SIZE;
int vertexBz = nwHeight;
final int c4 = seColor;
vertexBuffer.put(vertexAx, vertexAz, vertexAy, c3);
vertexBuffer.put(vertexBx, vertexBz, vertexBy, c4);
vertexBuffer.put(vertexCx, vertexCz, vertexCy, c2);
vertexBuffer.put(vertexDx, vertexDz, vertexDy, c1);
vertexBuffer.put(vertexCx, vertexCz, vertexCy, c2);
vertexBuffer.put(vertexBx, vertexBz, vertexBy, c4);
if (tile.getTexture() != -1)
{
float tex = tile.getTexture();
uvBuffer.put(tex, 1.0f + 1f, 1.0f + 1f, 0f);
uvBuffer.put(tex, 0.0f + 1f, 1.0f + 1f, 0f);
uvBuffer.put(tex, 1.0f + 1f, 0.0f + 1f, 0f);
uvBuffer.put(tex, 0.0f + 1f, 0.0f + 1f, 0f);
uvBuffer.put(tex, 1.0f + 1f, 0.0f + 1f, 0f);
uvBuffer.put(tex, 0.0f + 1f, 1.0f + 1f, 0f);
}
return 6;
}
private int upload(SceneTileModel sceneTileModel, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
{
final int[] faceX = sceneTileModel.getFaceX();
final int[] faceY = sceneTileModel.getFaceY();
final int[] faceZ = sceneTileModel.getFaceZ();
final int[] vertexX = sceneTileModel.getVertexX();
final int[] vertexY = sceneTileModel.getVertexY();
final int[] vertexZ = sceneTileModel.getVertexZ();
final int[] triangleColorA = sceneTileModel.getTriangleColorA();
final int[] triangleColorB = sceneTileModel.getTriangleColorB();
final int[] triangleColorC = sceneTileModel.getTriangleColorC();
final int[] triangleTextures = sceneTileModel.getTriangleTextureId();
final int faceCount = faceX.length;
vertexBuffer.ensureCapacity(faceCount * 12);
uvBuffer.ensureCapacity(faceCount * 12);
int baseX = Perspective.LOCAL_TILE_SIZE * tileX;
int baseY = Perspective.LOCAL_TILE_SIZE * tileY;
int cnt = 0;
for (int i = 0; i < faceCount; ++i)
{
final int triangleA = faceX[i];
final int triangleB = faceY[i];
final int triangleC = faceZ[i];
final int colorA = triangleColorA[i];
final int colorB = triangleColorB[i];
final int colorC = triangleColorC[i];
if (colorA == 12345678)
{
continue;
}
cnt += 3;
int vertexXA = vertexX[triangleA] - baseX;
int vertexZA = vertexZ[triangleA] - baseY;
int vertexXB = vertexX[triangleB] - baseX;
int vertexZB = vertexZ[triangleB] - baseY;
int vertexXC = vertexX[triangleC] - baseX;
int vertexZC = vertexZ[triangleC] - baseY;
vertexBuffer.put(vertexXA, vertexY[triangleA], vertexZA, colorA);
vertexBuffer.put(vertexXB, vertexY[triangleB], vertexZB, colorB);
vertexBuffer.put(vertexXC, vertexY[triangleC], vertexZC, colorC);
if (triangleTextures != null)
{
if (triangleTextures[i] != -1)
{
float tex = triangleTextures[i];
uvBuffer.put(tex, vertexXA / 128f + 1f, vertexZA / 128f + 1f, 0f);
uvBuffer.put(tex, vertexXB / 128f + 1f, vertexZB / 128f + 1f, 0f);
uvBuffer.put(tex, vertexXC / 128f + 1f, vertexZC / 128f + 1f, 0f);
}
else
{
uvBuffer.put(0, 0, 0, 0f);
uvBuffer.put(0, 0, 0, 0f);
uvBuffer.put(0, 0, 0, 0f);
}
}
}
return cnt;
}
private void uploadModel(Model model, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
{
if (model.getBufferOffset() > 0)
{
return;
}
model.setBufferOffset(offset);
if (model.getFaceTextures() != null)
{
model.setUvBufferOffset(uvoffset);
}
else
{
model.setUvBufferOffset(-1);
}
model.setSceneId(sceneId);
vertexBuffer.ensureCapacity(model.getTrianglesCount() * 12);
uvBuffer.ensureCapacity(model.getTrianglesCount() * 12);
final int triangleCount = model.getTrianglesCount();
int len = 0;
for (int i = 0; i < triangleCount; ++i)
{
len += pushFace(model, i, vertexBuffer, uvBuffer);
}
offset += len;
if (model.getFaceTextures() != null)
{
uvoffset += len;
}
}
int pushFace(Model model, int face, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
{
final int[] vertexX = model.getVerticesX();
final int[] vertexY = model.getVerticesY();
final int[] vertexZ = model.getVerticesZ();
final int[] trianglesX = model.getTrianglesX();
final int[] trianglesY = model.getTrianglesY();
final int[] trianglesZ = model.getTrianglesZ();
final int[] color1s = model.getFaceColors1();
final int[] color2s = model.getFaceColors2();
final int[] color3s = model.getFaceColors3();
final byte[] transparencies = model.getTriangleTransparencies();
final short[] faceTextures = model.getFaceTextures();
final byte[] facePriorities = model.getFaceRenderPriorities();
int triangleA = trianglesX[face];
int triangleB = trianglesY[face];
int triangleC = trianglesZ[face];
int color1 = color1s[face];
int color2 = color2s[face];
int color3 = color3s[face];
int alpha = 0;
if (transparencies != null)
{
alpha = (transparencies[face] & 0xFF) << 24;
}
int priority = 0;
if (facePriorities != null)
{
priority = (facePriorities[face] & 0xff) << 16;
}
if (color3 == -1)
{
color2 = color3 = color1;
}
else if (color3 == -2)
{
vertexBuffer.put(0, 0, 0, 0);
vertexBuffer.put(0, 0, 0, 0);
vertexBuffer.put(0, 0, 0, 0);
if (faceTextures != null)
{
uvBuffer.put(0, 0, 0, 0f);
uvBuffer.put(0, 0, 0, 0f);
uvBuffer.put(0, 0, 0, 0f);
}
return 3;
}
int a, b, c;
a = vertexX[triangleA];
b = vertexY[triangleA];
c = vertexZ[triangleA];
vertexBuffer.put(a, b, c, alpha | priority | color1);
a = vertexX[triangleB];
b = vertexY[triangleB];
c = vertexZ[triangleB];
vertexBuffer.put(a, b, c, alpha | priority | color2);
a = vertexX[triangleC];
b = vertexY[triangleC];
c = vertexZ[triangleC];
vertexBuffer.put(a, b, c, alpha | priority | color3);
float[][] u = model.getFaceTextureUCoordinates();
float[][] v = model.getFaceTextureVCoordinates();
float[] uf, vf;
if (faceTextures != null)
{
if (u != null && v != null && (uf = u[face]) != null && (vf = v[face]) != null)
{
final short texture = faceTextures[face];
uvBuffer.put(texture, 1f + uf[0], 1f + vf[0], 0f);
uvBuffer.put(texture, 1f + uf[1], 1f + vf[1], 0f);
uvBuffer.put(texture, 1f + uf[2], 1f + vf[2], 0f);
}
else
{
uvBuffer.put(0f, 0f, 0f, 0f);
uvBuffer.put(0f, 0f, 0f, 0f);
uvBuffer.put(0f, 0f, 0f, 0f);
}
}
return 3;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
class ShaderException extends Exception
{
ShaderException(String message)
{
super(message);
}
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import com.jogamp.opengl.GL4;
import java.nio.ByteBuffer;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Texture;
import net.runelite.api.TextureProvider;
@Singleton
@Slf4j
class TextureManager
{
private static final float PERC_64 = 1f / 64f;
private static final float PERC_128 = 1f / 128f;
private static final int SMALL_TEXTURE_SIZE = 64;
private static final int TEXTURE_SIZE = 128;
int initTextureArray(TextureProvider textureProvider, GL4 gl)
{
if (!allTexturesLoaded(textureProvider))
{
return -1;
}
Texture[] textures = textureProvider.getTextures();
int textureArrayId = GLUtil.glGenTexture(gl);
gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, textureArrayId);
gl.glTexStorage3D(gl.GL_TEXTURE_2D_ARRAY, 1, gl.GL_RGBA8, TEXTURE_SIZE, TEXTURE_SIZE, textures.length);
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST);
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST);
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE);
// Set brightness to 1.0d to upload unmodified textures to GPU
double save = textureProvider.getBrightness();
textureProvider.setBrightness(1.0d);
updateTextures(textureProvider, gl, textureArrayId);
textureProvider.setBrightness(save);
gl.glActiveTexture(gl.GL_TEXTURE1);
gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, textureArrayId);
gl.glActiveTexture(gl.GL_TEXTURE0);
return textureArrayId;
}
void freeTextureArray(GL4 gl, int textureArrayId)
{
GLUtil.glDeleteTexture(gl, textureArrayId);
}
/**
* Check if all textures have been loaded and cached yet.
*
* @param textureProvider
* @return
*/
private boolean allTexturesLoaded(TextureProvider textureProvider)
{
Texture[] textures = textureProvider.getTextures();
if (textures == null || textures.length == 0)
{
return false;
}
for (int textureId = 0; textureId < textures.length; textureId++)
{
Texture texture = textures[textureId];
if (texture != null)
{
int[] pixels = textureProvider.load(textureId);
if (pixels == null)
{
return false;
}
}
}
return true;
}
private void updateTextures(TextureProvider textureProvider, GL4 gl, int textureArrayId)
{
Texture[] textures = textureProvider.getTextures();
gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, textureArrayId);
int cnt = 0;
for (int textureId = 0; textureId < textures.length; textureId++)
{
Texture texture = textures[textureId];
if (texture != null)
{
int[] srcPixels = textureProvider.load(textureId);
if (srcPixels == null)
{
log.warn("No pixels for texture {}!", textureId);
continue; // this can't happen
}
++cnt;
int srcSize = srcPixels.length == 4096 ? SMALL_TEXTURE_SIZE : TEXTURE_SIZE;
byte[] pixels = convertPixels(srcPixels, srcSize, srcSize, TEXTURE_SIZE, TEXTURE_SIZE);
ByteBuffer pixelBuffer = ByteBuffer.wrap(pixels);
gl.glTexSubImage3D(gl.GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureId, TEXTURE_SIZE, TEXTURE_SIZE,
1, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, pixelBuffer);
}
}
log.debug("Uploaded textures {}", cnt);
}
private static byte[] convertPixels(int[] srcPixels, int width, int height, int textureWidth, int textureHeight)
{
byte[] pixels = new byte[textureWidth * textureHeight * 4];
int pixelIdx = 0;
int srcPixelIdx = 0;
int offset = (textureWidth - width) * 4;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int rgb = srcPixels[srcPixelIdx++];
if (rgb != 0)
{
pixels[pixelIdx++] = (byte) (rgb >> 16);
pixels[pixelIdx++] = (byte) (rgb >> 8);
pixels[pixelIdx++] = (byte) rgb;
pixels[pixelIdx++] = (byte) -1;
}
else
{
pixelIdx += 4;
}
}
pixelIdx += offset;
}
return pixels;
}
/**
* Animate the given texture
*
* @param texture
* @param diff Number of elapsed client ticks since last animation
*/
void animate(Texture texture, int diff)
{
final int[] pixels = texture.getPixels();
if (pixels == null)
{
return;
}
final int animationSpeed = texture.getAnimationSpeed();
final float uvdiff = pixels.length == 4096 ? PERC_64 : PERC_128;
float u = texture.getU();
float v = texture.getV();
int offset = animationSpeed * diff;
float d = (float) offset * uvdiff;
switch (texture.getAnimationDirection())
{
case 1:
v -= d;
if (v < 0f)
{
v += 1f;
}
break;
case 3:
v += d;
if (v > 1f)
{
v -= 1f;
}
break;
case 2:
u -= d;
if (u < 0f)
{
u += 1f;
}
break;
case 4:
u += d;
if (u > 1f)
{
u -= 1f;
}
break;
default:
return;
}
texture.setU(u);
texture.setV(v);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu.template;
import java.util.function.Function;
public class Template
{
private final Function<String, String> resourceLoader;
public Template(Function<String, String> resourceLoader)
{
this.resourceLoader = resourceLoader;
}
public String process(String str)
{
StringBuilder sb = new StringBuilder();
for (String line : str.split("\r?\n"))
{
if (line.startsWith("#include "))
{
String resource = line.substring(9);
String resourceStr = resourceLoader.apply(resource);
sb.append(process(resourceStr));
}
else
{
sb.append(line).append('\n');
}
}
return sb.toString();
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#include to_screen.glsl
/*
* Rotate a vertex by a given orientation in JAU
*/
ivec4 rotate(ivec4 vertex, int orientation) {
int s = int(65536.0f * sin(orientation * UNIT));
int c = int(65536.0f * cos(orientation * UNIT));
int x = vertex.z * s + vertex.x * c >> 16;
int z = vertex.z * c - vertex.x * s >> 16;
return ivec4(x, vertex.y, z, vertex.w);
}
/*
* Calculate the distance to a vertex given the camera angle
*/
int distance(ivec4 vertex, int cameraYaw, int cameraPitch) {
int yawSin = int(65536.0f * sin(cameraYaw * UNIT));
int yawCos = int(65536.0f * cos(cameraYaw * UNIT));
int pitchSin = int(65536.0f * sin(cameraPitch * UNIT));
int pitchCos = int(65536.0f * cos(cameraPitch * UNIT));
int j = vertex.z * yawCos - vertex.x * yawSin >> 16;
int l = vertex.y * pitchSin + j * pitchCos >> 16;
return l;
}
/*
* Calculate the distance to a face
*/
int face_distance(ivec4 vA, ivec4 vB, ivec4 vC, int cameraYaw, int cameraPitch) {
int dvA = distance(vA, cameraYaw, cameraPitch);
int dvB = distance(vB, cameraYaw, cameraPitch);
int dvC = distance(vC, cameraYaw, cameraPitch);
int faceDistance = (dvA + dvB + dvC) / 3;
return faceDistance;
}
/*
* Test if a face is visible (not backward facing)
*/
bool face_visible(ivec4 vA, ivec4 vB, ivec4 vC, ivec4 position, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom) {
vA += position;
vB += position;
vC += position;
ivec3 sA = toScreen(vA.xyz, cameraYaw, cameraPitch, centerX, centerY, zoom);
ivec3 sB = toScreen(vB.xyz, cameraYaw, cameraPitch, centerX, centerY, zoom);
ivec3 sC = toScreen(vC.xyz, cameraYaw, cameraPitch, centerX, centerY, zoom);
return (sA.x - sB.x) * (sC.y - sB.y) - (sC.x - sB.x) * (sA.y - sB.y) > 0;
}
// Calculate adjusted priority for a face with a given priority, distance, and
// model global min10 and face distance averages. This allows positioning faces
// with priorities 10/11 into the correct 'slots' resulting in 18 possible
// adjusted priorities
int priority_map(int p, int distance, int _min10, int avg1, int avg2, int avg3) {
// (10, 11) 0 1 2 (10, 11) 3 4 (10, 11) 5 6 7 8 9 (10, 11)
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
switch (p) {
case 0: return 2;
case 1: return 3;
case 2: return 4;
case 3: return 7;
case 4: return 8;
case 5: return 11;
case 6: return 12;
case 7: return 13;
case 8: return 14;
case 9: return 15;
case 10:
if (distance > avg1) {
return 0;
} else if (distance > avg2) {
return 5;
} else if (distance > avg3) {
return 9;
} else {
return 16;
}
case 11:
if (distance > avg1 && _min10 > avg1) {
return 1;
} else if (distance > avg2 && (_min10 > avg1 || _min10 > avg2)) {
return 6;
} else if (distance > avg3 && (_min10 > avg1 || _min10 > avg2 || _min10 > avg3)) {
return 10;
} else {
return 17;
}
default:
return -1;
}
}
// calculate the number of faces with a lower adjusted priority than
// the given adjusted priority
int count_prio_offset(int priority) {
int total = 0;
switch (priority) {
case 17:
total += totalMappedNum[16];
case 16:
total += totalMappedNum[15];
case 15:
total += totalMappedNum[14];
case 14:
total += totalMappedNum[13];
case 13:
total += totalMappedNum[12];
case 12:
total += totalMappedNum[11];
case 11:
total += totalMappedNum[10];
case 10:
total += totalMappedNum[9];
case 9:
total += totalMappedNum[8];
case 8:
total += totalMappedNum[7];
case 7:
total += totalMappedNum[6];
case 6:
total += totalMappedNum[5];
case 5:
total += totalMappedNum[4];
case 4:
total += totalMappedNum[3];
case 3:
total += totalMappedNum[2];
case 2:
total += totalMappedNum[1];
case 1:
total += totalMappedNum[0];
case 0:
return total;
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 430 core
#define PI 3.1415926535897932384626433832795f
#define UNIT PI / 1024.0f
layout(std140) uniform uniforms {
int cameraYaw;
int cameraPitch;
int centerX;
int centerY;
int zoom;
};
shared int totalNum[12]; // number of faces with a given priority
shared int totalDistance[12]; // sum of distances to faces of a given priority
shared int totalMappedNum[18]; // number of faces with a given adjusted priority
shared int min10; // minimum distance to a face of priority 10
shared int dfs[4096]; // packed face id and distance
struct modelinfo {
int offset; // offset into buffer
int uvOffset; // offset into uv buffer
int length; // length in faces
int idx; // write idx in target buffer
int flags; // radius, orientation
int x; // scene position x
int y; // scene position y
int z; // scene position z
};
layout(std430, binding = 0) readonly buffer modelbuffer_in {
modelinfo ol[];
};
layout(std430, binding = 1) readonly buffer vertexbuffer_in {
ivec4 vb[];
};
layout(std430, binding = 2) readonly buffer tempvertexbuffer_in {
ivec4 tempvb[];
};
layout(std430, binding = 3) writeonly buffer vertex_out {
ivec4 vout[];
};
layout(std430, binding = 4) writeonly buffer uv_out {
vec4 uvout[];
};
layout(std430, binding = 5) readonly buffer uvbuffer_in {
vec4 uv[];
};
layout(std430, binding = 6) readonly buffer tempuvbuffer_in {
vec4 tempuv[];
};
layout(local_size_x = 1024) in;
#include common.glsl
#include priority_render.glsl
void main() {
uint groupId = gl_WorkGroupID.x;
uint localId = gl_LocalInvocationID.x * 4;
modelinfo minfo = ol[groupId];
int length = minfo.length;
if (localId == 0) {
min10 = 1600;
for (int i = 0; i < 12; ++i) {
totalNum[i] = 0;
totalDistance[i] = 0;
}
for (int i = 0; i < 18; ++i) {
totalMappedNum[i] = 0;
}
}
memoryBarrierShared();
barrier();
int prio1, dis1, prio1Adj;
ivec4 vA1, vA2, vA3;
int prio2, dis2, prio2Adj;
ivec4 vB1, vB2, vB3;
int prio3, dis3, prio3Adj;
ivec4 vC1, vC2, vC3;
int prio4, dis4, prio4Adj;
ivec4 vD1, vD2, vD3;
get_face(localId, minfo, cameraYaw, cameraPitch, centerX, centerY, zoom, prio1, dis1, vA1, vA2, vA3);
get_face(localId + 1, minfo, cameraYaw, cameraPitch, centerX, centerY, zoom, prio2, dis2, vB1, vB2, vB3);
get_face(localId + 2, minfo, cameraYaw, cameraPitch, centerX, centerY, zoom, prio3, dis3, vC1, vC2, vC3);
get_face(localId + 3, minfo, cameraYaw, cameraPitch, centerX, centerY, zoom, prio4, dis4, vD1, vD2, vD3);
memoryBarrierShared();
barrier();
int idx1 = map_face_priority(localId, minfo, prio1, dis1, prio1Adj);
int idx2 = map_face_priority(localId + 1, minfo, prio2, dis2, prio2Adj);
int idx3 = map_face_priority(localId + 2, minfo, prio3, dis3, prio3Adj);
int idx4 = map_face_priority(localId + 3, minfo, prio4, dis4, prio4Adj);
memoryBarrierShared();
barrier();
insert_dfs(localId , minfo, prio1Adj, dis1, idx1);
insert_dfs(localId + 1, minfo, prio2Adj, dis2, idx2);
insert_dfs(localId + 2, minfo, prio3Adj, dis3, idx3);
insert_dfs(localId + 3, minfo, prio4Adj, dis4, idx4);
memoryBarrierShared();
barrier();
sort_and_insert(localId , minfo, prio1Adj, dis1, vA1, vA2, vA3);
sort_and_insert(localId + 1, minfo, prio2Adj, dis2, vB1, vB2, vB3);
sort_and_insert(localId + 2, minfo, prio3Adj, dis3, vC1, vC2, vC3);
sort_and_insert(localId + 3, minfo, prio4Adj, dis4, vD1, vD2, vD3);
}

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 430 core
#define PI 3.1415926535897932384626433832795f
#define UNIT PI / 1024.0f
layout(std140) uniform uniforms {
int cameraYaw;
int cameraPitch;
int centerX;
int centerY;
int zoom;
};
shared int totalNum[12]; // number of faces with a given priority
shared int totalDistance[12]; // sum of distances to faces of a given priority
shared int totalMappedNum[18]; // number of faces with a given adjusted priority
shared int min10; // minimum distance to a face of priority 10
shared int dfs[512]; // packed face id and distance
struct modelinfo {
int offset; // offset into buffer
int uvOffset; // offset into uv buffer
int length; // length in faces
int idx; // write idx in target buffer
int flags; // radius, orientation
int x; // scene position x
int y; // scene position y
int z; // scene position z
};
layout(std430, binding = 0) readonly buffer modelbuffer_in {
modelinfo ol[];
};
layout(std430, binding = 1) readonly buffer vertexbuffer_in {
ivec4 vb[];
};
layout(std430, binding = 2) readonly buffer tempvertexbuffer_in {
ivec4 tempvb[];
};
layout(std430, binding = 3) writeonly buffer vertex_out {
ivec4 vout[];
};
layout(std430, binding = 4) writeonly buffer uv_out {
vec4 uvout[];
};
layout(std430, binding = 5) readonly buffer uvbuffer_in {
vec4 uv[];
};
layout(std430, binding = 6) readonly buffer tempuvbuffer_in {
vec4 tempuv[];
};
layout(local_size_x = 512) in;
#include common.glsl
#include priority_render.glsl
void main() {
uint groupId = gl_WorkGroupID.x;
uint localId = gl_LocalInvocationID.x;
modelinfo minfo = ol[groupId];
if (localId == 0) {
min10 = 1600;
for (int i = 0; i < 12; ++i) {
totalNum[i] = 0;
totalDistance[i] = 0;
}
for (int i = 0; i < 18; ++i) {
totalMappedNum[i] = 0;
}
}
memoryBarrierShared();
barrier();
int prio1, dis1, prio1Adj;
ivec4 vA1, vA2, vA3;
get_face(localId, minfo, cameraYaw, cameraPitch, centerX, centerY, zoom, prio1, dis1, vA1, vA2, vA3);
memoryBarrierShared();
barrier();
int idx1 = map_face_priority(localId, minfo, prio1, dis1, prio1Adj);
memoryBarrierShared();
barrier();
insert_dfs(localId, minfo, prio1Adj, dis1, idx1);
memoryBarrierShared();
barrier();
sort_and_insert(localId, minfo, prio1Adj, dis1, vA1, vA2, vA3);
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 400
uniform sampler2DArray textures;
uniform vec2 textureOffsets[64];
uniform float brightness;
in vec4 Color;
in vec4 fUv;
out vec4 FragColor;
void main() {
float n = fUv.x;
float u = fUv.y;
float v = fUv.z;
if (u > 0.0f && v > 0.0f) {
int textureIdx = int(n);
vec2 uv = vec2(u - 1, v - 1);
vec2 animatedUv = uv + textureOffsets[textureIdx];
vec4 textureColor = texture(textures, vec3(animatedUv, n));
vec4 textureColorBrightness = pow(textureColor, vec4(brightness, brightness, brightness, 1.0f));
FragColor = textureColorBrightness * Color;
} else {
FragColor = Color;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 330
uniform sampler2D tex;
in vec2 TexCoord;
out vec4 FragColor;
void main() {
vec4 c = texture(tex, TexCoord);
FragColor = c;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 400
#define PI 3.1415926535897932384626433832795f
#define UNIT PI / 1024.0f
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
layout(std140) uniform Uniforms {
int cameraYaw;
int cameraPitch;
int centerX;
int centerY;
int zoom;
};
uniform mat4 projectionMatrix;
in ivec3 vPosition[];
in vec4 vColor[];
in vec4 vUv[];
out vec4 Color;
out vec4 fUv;
#include to_screen.glsl
void main() {
ivec3 screenA = toScreen(vPosition[0], cameraYaw, cameraPitch, centerX, centerY, zoom);
ivec3 screenB = toScreen(vPosition[1], cameraYaw, cameraPitch, centerX, centerY, zoom);
ivec3 screenC = toScreen(vPosition[2], cameraYaw, cameraPitch, centerX, centerY, zoom);
if (-screenA.z < 50 || -screenB.z < 50 || -screenC.z < 50) {
// the client does not draw a triangle if any vertex distance is <50
return;
}
vec4 tmp = vec4(screenA.xyz, 1.0);
Color = vColor[0];
fUv = vUv[0];
gl_Position = projectionMatrix * tmp;
EmitVertex();
tmp = vec4(screenB.xyz, 1.0);
Color = vColor[1];
fUv = vUv[1];
gl_Position = projectionMatrix * tmp;
EmitVertex();
tmp = vec4(screenC.xyz, 1.0);
Color = vColor[2];
fUv = vUv[2];
gl_Position = projectionMatrix * tmp;
EmitVertex();
EndPrimitive();
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
void get_face(uint localId, modelinfo minfo, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom,
out int prio, out int dis, out ivec4 o1, out ivec4 o2, out ivec4 o3) {
int offset = minfo.offset;
int length = minfo.length;
int flags = minfo.flags;
int radius = (flags & 0x7fffffff) >> 12;
int orientation = flags & 0x7ff;
ivec4 pos = ivec4(minfo.x, minfo.y, minfo.z, 0);
uint ssboOffset;
if (localId < length) {
ssboOffset = localId;
} else {
ssboOffset = 0;
}
ivec4 thisA;
ivec4 thisB;
ivec4 thisC;
// Grab triangle vertices from the correct buffer
if (flags < 0) {
thisA = vb[offset + ssboOffset * 3 ];
thisB = vb[offset + ssboOffset * 3 + 1];
thisC = vb[offset + ssboOffset * 3 + 2];
} else {
thisA = tempvb[offset + ssboOffset * 3 ];
thisB = tempvb[offset + ssboOffset * 3 + 1];
thisC = tempvb[offset + ssboOffset * 3 + 2];
}
ivec4 thisrvA;
ivec4 thisrvB;
ivec4 thisrvC;
int thisPriority, thisDistance;
if (localId < length) {
// rotate for model orientation
thisrvA = rotate(thisA, orientation);
thisrvB = rotate(thisB, orientation);
thisrvC = rotate(thisC, orientation);
// calculate distance to face
thisPriority = (thisA.w >> 16) & 0xff; // all vertices on the face have the same priority
if (radius == 0) {
thisDistance = 0;
} else {
thisDistance = face_distance(thisrvA, thisrvB, thisrvC, cameraYaw, cameraPitch) + radius;
}
// if the face is not culled, it is calculated into priority distance averages
if (face_visible(thisrvA, thisrvB, thisrvC, pos, cameraYaw, cameraPitch, centerX, centerY, zoom)) {
atomicAdd(totalNum[thisPriority], 1);
atomicAdd(totalDistance[thisPriority], thisDistance);
// calculate minimum distance to any face of priority 10 for positioning the 11 faces later
if (thisPriority == 10) {
atomicMin(min10, thisDistance);
}
}
o1 = thisrvA;
o2 = thisrvB;
o3 = thisrvC;
prio = thisPriority;
dis = thisDistance;
} else {
prio = 0;
dis = 0;
}
}
int map_face_priority(uint localId, modelinfo minfo, int thisPriority, int thisDistance, out int prio) {
int length = minfo.length;
// Compute average distances for 0/2, 3/4, and 6/8
int adjPrio;
int prioIdx;
if (localId < length) {
int avg1 = 0;
int avg2 = 0;
int avg3 = 0;
if (totalNum[1] > 0 || totalNum[2] > 0) {
avg1 = (totalDistance[1] + totalDistance[2]) / (totalNum[1] + totalNum[2]);
}
if (totalNum[3] > 0 || totalNum[4] > 0) {
avg2 = (totalDistance[3] + totalDistance[4]) / (totalNum[3] + totalNum[4]);
}
if (totalNum[6] > 0 || totalNum[8] > 0) {
avg3 = (totalDistance[6] + totalDistance[8]) / (totalNum[6] + totalNum[8]);
}
int _min10 = min10;
adjPrio = priority_map(thisPriority, thisDistance, _min10, avg1, avg2, avg3);
int prioIdx = atomicAdd(totalMappedNum[adjPrio], 1);
prio = adjPrio;
return prioIdx;
}
return 0;
}
void insert_dfs(uint localId, modelinfo minfo, int adjPrio, int distance, int prioIdx) {
int length = minfo.length;
if (localId < length) {
// calculate base offset into dfs based on number of faces with a lower priority
int baseOff = count_prio_offset(adjPrio);
// store into face array offset array by unique index
dfs[baseOff + prioIdx] = (int(localId) << 16) | distance;
}
}
void sort_and_insert(uint localId, modelinfo minfo, int thisPriority, int thisDistance, ivec4 thisrvA, ivec4 thisrvB, ivec4 thisrvC) {
/* compute face distance */
int length = minfo.length;
int outOffset = minfo.idx;
int uvOffset = minfo.uvOffset;
int flags = minfo.flags;
ivec4 pos = ivec4(minfo.x, minfo.y, minfo.z, 0);
int start, end, myOffset;
if (localId < length) {
const int priorityOffset = count_prio_offset(thisPriority);
const int numOfPriority = totalMappedNum[thisPriority];
start = priorityOffset; // index of first face with this priority
end = priorityOffset + numOfPriority; // index of last face with this priority
myOffset = priorityOffset;
} else {
start = end = myOffset = 0;
}
if (localId < length) {
// we only have to order faces against others of the same priority
// calculate position this face will be in
for (int i = start; i < end; ++i) {
int d1 = dfs[i];
int theirId = d1 >> 16;
int theirDistance = d1 & 0xffff;
// the closest faces draw last, so have the highest index
// if two faces have the same distance, the one with the
// higher id draws last
if ((theirDistance > thisDistance)
|| (theirDistance == thisDistance && theirId < localId)) {
++myOffset;
}
}
// position vertices in scene and write to out buffer
vout[outOffset + myOffset * 3] = pos + thisrvA;
vout[outOffset + myOffset * 3 + 1] = pos + thisrvB;
vout[outOffset + myOffset * 3 + 2] = pos + thisrvC;
if (uvOffset < 0) {
uvout[outOffset + myOffset * 3] = vec4(0, 0, 0, 0);
uvout[outOffset + myOffset * 3 + 1] = vec4(0, 0, 0, 0);
uvout[outOffset + myOffset * 3 + 2] = vec4(0, 0, 0, 0);
} else if (flags >= 0) {
uvout[outOffset + myOffset * 3] = tempuv[uvOffset + localId * 3];
uvout[outOffset + myOffset * 3 + 1] = tempuv[uvOffset + localId * 3 + 1];
uvout[outOffset + myOffset * 3 + 2] = tempuv[uvOffset + localId * 3 + 2];
} else {
uvout[outOffset + myOffset * 3] = uv[uvOffset + localId * 3];
uvout[outOffset + myOffset * 3 + 1] = uv[uvOffset + localId * 3 + 1];
uvout[outOffset + myOffset * 3 + 2] = uv[uvOffset + localId * 3 + 2];
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
/*
* Convert a vertex to screen space
*/
ivec3 toScreen(ivec3 vertex, int cameraYaw, int cameraPitch, int centerX, int centerY, int zoom) {
int yawSin = int(65536.0f * sin(cameraYaw * UNIT));
int yawCos = int(65536.0f * cos(cameraYaw * UNIT));
int pitchSin = int(65536.0f * sin(cameraPitch * UNIT));
int pitchCos = int(65536.0f * cos(cameraPitch * UNIT));
int rotatedX = ((vertex.z * yawSin) + (vertex.x * yawCos)) >> 16;
int rotatedZ = ((vertex.z * yawCos) - (vertex.x * yawSin)) >> 16;
int var13 = ((vertex.y * pitchCos) - (rotatedZ * pitchSin)) >> 16;
int var12 = ((vertex.y * pitchSin) + (rotatedZ * pitchCos)) >> 16;
int x = rotatedX * zoom / var12 + centerX;
int y = var13 * zoom / var12 + centerY;
int z = -var12; // in OpenGL depth is negative
return ivec3(x, y, z);
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 400
layout (location = 0) in ivec4 VertexPosition;
layout (location = 1) in vec4 uv;
uniform float brightness;
out ivec3 vPosition;
out vec4 vColor;
out vec4 vUv;
vec3 hslToRgb(int hsl) {
int var5 = hsl/128;
float var6 = float(var5 >> 3) / 64.0f + 0.0078125f;
float var8 = float(var5 & 7) / 8.0f + 0.0625f;
int var10 = hsl % 128;
float var11 = float(var10) / 128.0f;
float var13 = var11;
float var15 = var11;
float var17 = var11;
if(var8 != 0.0f) {
float var19;
if(var11 < 0.5f) {
var19 = var11 * (1.0f + var8);
} else {
var19 = var11 + var8 - var11 * var8;
}
float var21 = 2.0f * var11 - var19;
float var23 = var6 + 0.3333333333333333f;
if(var23 > 1.0f) {
var23 -= 1.f;
}
float var27 = var6 - 0.3333333333333333f;
if(var27 < 0.0f) {
var27 += 1.f;
}
if(6.0f * var23 < 1.0f) {
var13 = var21 + (var19 - var21) * 6.0f * var23;
} else if(2.0f * var23 < 1.0f) {
var13 = var19;
} else if(3.0f * var23 < 2.0f) {
var13 = var21 + (var19 - var21) * (0.6666666666666666f - var23) * 6.0f;
} else {
var13 = var21;
}
if(6.0f * var6 < 1.0f) {
var15 = var21 + (var19 - var21) * 6.0f * var6;
} else if(2.0f * var6 < 1.0f) {
var15 = var19;
} else if(3.0f * var6 < 2.0f) {
var15 = var21 + (var19 - var21) * (0.6666666666666666f - var6) * 6.0f;
} else {
var15 = var21;
}
if(6.0f * var27 < 1.0f) {
var17 = var21 + (var19 - var21) * 6.0f * var27;
} else if(2.0f * var27 < 1.0f) {
var17 = var19;
} else if(3.0f * var27 < 2.0f) {
var17 = var21 + (var19 - var21) * (0.6666666666666666f - var27) * 6.0f;
} else {
var17 = var21;
}
}
vec3 rgb = vec3(
pow(var13, brightness),
pow(var15, brightness),
pow(var17, brightness)
);
// I don't think we actually need this
if (rgb == vec3(0, 0, 0)) {
rgb = vec3(0, 0, 1/255.f);
}
return rgb;
}
void main()
{
ivec3 vertex = VertexPosition.xyz;
int ahsl = VertexPosition.w;
int hsl = ahsl & 0xffff;
float a = float(ahsl >> 24 & 0xff) / 255.f;
vec3 rgb = hslToRgb(hsl);
vPosition = vertex;
vColor = vec4(rgb, 1.f - a);
vUv = uv;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
#version 330
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
TexCoord = aTexCoord;
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu;
import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
import com.jogamp.nativewindow.NativeWindowFactory;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.opengl.GL4;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawable;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLProfile;
import java.awt.Canvas;
import java.util.function.Function;
import javax.swing.JFrame;
import static net.runelite.client.plugins.gpu.GLUtil.inputStreamToString;
import net.runelite.client.plugins.gpu.template.Template;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class ShaderTest
{
private static final String VERTEX_SHADER = "" +
"void main() {" +
" gl_Position = vec4(1.0, 1.0, 1.0, 1.0);" +
"}";
private GL4 gl;
@Before
public void before()
{
Canvas canvas = new Canvas();
JFrame frame = new JFrame();
frame.setSize(100, 100);
frame.add(canvas);
frame.setVisible(true);
GLProfile glProfile = GLProfile.getMaxFixedFunc(true);
GLCapabilities glCaps = new GLCapabilities(glProfile);
AbstractGraphicsConfiguration config = AWTGraphicsConfiguration.create(canvas.getGraphicsConfiguration(),
glCaps, glCaps);
JAWTWindow jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(canvas, config);
GLDrawableFactory glDrawableFactory = GLDrawableFactory.getFactory(glProfile);
GLDrawable glDrawable = glDrawableFactory.createGLDrawable(jawtWindow);
glDrawable.setRealized(true);
GLContext glContext = glDrawable.createContext(null);
int res = glContext.makeCurrent();
if (res == GLContext.CONTEXT_NOT_CURRENT)
{
fail("error making context current");
}
gl = glContext.getGL().getGL4();
}
@Test
@Ignore
public void testSmall() throws ShaderException
{
int glComputeProgram = gl.glCreateProgram();
int glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER);
try
{
Function<String, String> func = (s) -> inputStreamToString(getClass().getResourceAsStream(s));
Template template = new Template(func);
String source = template.process(func.apply("comp_small.glsl"));
int line = 0;
for (String str : source.split("\\n"))
{
System.out.println(++line + " " + str);
}
GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source);
}
finally
{
gl.glDeleteShader(glComputeShader);
gl.glDeleteProgram(glComputeProgram);
}
}
@Test
@Ignore
public void testComp() throws ShaderException
{
int glComputeProgram = gl.glCreateProgram();
int glComputeShader = gl.glCreateShader(gl.GL_COMPUTE_SHADER);
try
{
Function<String, String> func = (s) -> inputStreamToString(getClass().getResourceAsStream(s));
Template template = new Template(func);
String source = template.process(func.apply("comp.glsl"));
int line = 0;
for (String str : source.split("\\n"))
{
System.out.println(++line + " " + str);
}
GLUtil.loadComputeShader(gl, glComputeProgram, glComputeShader, source);
}
finally
{
gl.glDeleteShader(glComputeShader);
gl.glDeleteProgram(glComputeProgram);
}
}
@Test
@Ignore
public void testGeom() throws ShaderException
{
int glComputeProgram = gl.glCreateProgram();
int glVertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER);
int glGeometryShader = gl.glCreateShader(gl.GL_GEOMETRY_SHADER);
int glFragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER);
try
{
Function<String, String> func = (s) -> inputStreamToString(getClass().getResourceAsStream(s));
Template template = new Template(func);
String source = template.process(func.apply("geom.glsl"));
int line = 0;
for (String str : source.split("\\n"))
{
System.out.println(++line + " " + str);
}
GLUtil.loadShaders(gl, glComputeProgram, glVertexShader, glGeometryShader, glFragmentShader, VERTEX_SHADER, source, "");
}
finally
{
gl.glDeleteShader(glVertexShader);
gl.glDeleteShader(glGeometryShader);
gl.glDeleteShader(glFragmentShader);
gl.glDeleteProgram(glComputeProgram);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.client.plugins.gpu.template;
import java.util.function.Function;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class TemplateTest
{
private static final String FILE1 = "" +
"test1\n" +
"#include file2\n" +
"test3\n";
private static final String FILE2 = "" +
"test4\n" +
"test5\n";
private static final String RESULT = "" +
"test1\n" +
"test4\n" +
"test5\n" +
"test3\n";
@Test
public void testProcess()
{
Function<String, String> func = (String resource) ->
{
switch (resource)
{
case "file2":
return FILE2;
default:
throw new RuntimeException("unknown resource");
}
};
String out = new Template(func).process(FILE1);
assertEquals(RESULT, out);
}
}

View File

@@ -58,6 +58,19 @@
<version>1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>

View File

@@ -0,0 +1,314 @@
package net.runelite.mixins;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSModel;
/**
* Class to check clickboxes of models. Mostly refactored code from the client.
*/
@Mixin(RSClient.class)
public abstract class ClickboxMixin implements RSClient
{
@Shadow("clientInstance")
private static RSClient client;
private static final int MAX_ENTITES_AT_MOUSE = 1000;
private static final int CLICKBOX_CLOSE = 50;
private static final int CLICKBOX_FAR = 3500;
@Inject
private static final int[] rl$modelViewportXs = new int[4700];
@Inject
private static final int[] rl$modelViewportYs = new int[4700];
@Inject
public void checkClickbox(Model rlModel, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int _x, int _y, int _z, long hash)
{
RSModel model = (RSModel) rlModel;
boolean hasFlag = hash != 0L && (int) (hash >>> 16 & 1L) != 1;
boolean viewportContainsMouse = client.getViewportContainsMouse();
if (!hasFlag || !viewportContainsMouse || client.getOculusOrbState() != 0)
{
return;
}
boolean bb = boundingboxCheck(model, _x, _y, _z);
if (!bb)
{
return;
}
// only need a boundingbox check?
if (model.isClickable())
{
addHashAtMouse(hash);
return;
}
// otherwise we must check if the mouse is in a triangle
final int vertexCount = model.getVerticesCount();
final int triangleCount = model.getTrianglesCount();
final int[] vertexX = model.getVerticesX();
final int[] vertexY = model.getVerticesY();
final int[] vertexZ = model.getVerticesZ();
final int[] triangleX = model.getTrianglesX();
final int[] triangleY = model.getTrianglesY();
final int[] triangleZ = model.getTrianglesZ();
final int[] color3 = model.getFaceColors3();
final int zoom = client.get3dZoom();
final int centerX = client.getCenterX();
final int centerY = client.getCenterY();
int sin = 0;
int cos = 0;
if (orientation != 0)
{
sin = Perspective.SINE[orientation];
cos = Perspective.COSINE[orientation];
}
for (int i = 0; i < vertexCount; ++i)
{
int x = vertexX[i];
int y = vertexY[i];
int z = vertexZ[i];
int var42;
if (orientation != 0)
{
var42 = z * sin + x * cos >> 16;
z = z * cos - x * sin >> 16;
x = var42;
}
x += _x;
y += _y;
z += _z;
var42 = z * yawSin + yawCos * x >> 16;
z = yawCos * z - x * yawSin >> 16;
x = var42;
var42 = pitchCos * y - z * pitchSin >> 16;
z = y * pitchSin + pitchCos * z >> 16;
if (z >= 50)
{
rl$modelViewportYs[i] = x * zoom / z + centerX;
rl$modelViewportXs[i] = var42 * zoom / z + centerY;
}
else
{
rl$modelViewportYs[i] = -5000;
}
}
final int viewportMouseX = client.getViewportMouseX();
final int viewportMouseY = client.getViewportMouseY();
for (int i = 0; i < triangleCount; ++i)
{
if (color3[i] == -2)
{
continue;
}
final int vA = triangleX[i];
final int vB = triangleY[i];
final int vC = triangleZ[i];
int y1 = rl$modelViewportYs[vA];
int y2 = rl$modelViewportYs[vB];
int y3 = rl$modelViewportYs[vC];
int x1 = rl$modelViewportXs[vA];
int x2 = rl$modelViewportXs[vB];
int x3 = rl$modelViewportXs[vC];
if (y1 == -5000 || y2 == -5000 || y3 == -5000)
{
continue;
}
final int radius = model.isClickable() ? 20 : 5;
int var18 = radius + viewportMouseY;
boolean var34;
if (var18 < x1 && var18 < x2 && var18 < x3)
{
var34 = false;
}
else
{
var18 = viewportMouseY - radius;
if (var18 > x1 && var18 > x2 && var18 > x3)
{
var34 = false;
}
else
{
var18 = radius + viewportMouseX;
if (var18 < y1 && var18 < y2 && var18 < y3)
{
var34 = false;
}
else
{
var18 = viewportMouseX - radius;
if (var18 > y1 && var18 > y2 && var18 > y3)
{
var34 = false;
}
else
{
var34 = true;
}
}
}
}
if (var34)
{
addHashAtMouse(hash);
break;
}
}
}
@Inject
private void addHashAtMouse(long hash)
{
long[] entitiesAtMouse = client.getEntitiesAtMouse();
int count = client.getEntitiesAtMouseCount();
if (count < MAX_ENTITES_AT_MOUSE)
{
entitiesAtMouse[count] = hash;
client.setEntitiesAtMouseCount(count + 1);
}
}
@Inject
private boolean boundingboxCheck(Model model, int x, int y, int z)
{
final int cameraPitch = client.getCameraPitch();
final int cameraYaw = client.getCameraYaw();
final int pitchSin = Perspective.SINE[cameraPitch];
final int pitchCos = Perspective.COSINE[cameraPitch];
final int yawSin = Perspective.SINE[cameraYaw];
final int yawCos = Perspective.COSINE[cameraYaw];
final int centerX = client.getCenterX();
final int centerY = client.getCenterY();
final int viewportMouseX = client.getViewportMouseX();
final int viewportMouseY = client.getViewportMouseY();
final int Rasterizer3D_zoom = client.get3dZoom();
int var6 = (viewportMouseX - centerX) * CLICKBOX_CLOSE / Rasterizer3D_zoom;
int var7 = (viewportMouseY - centerY) * CLICKBOX_CLOSE / Rasterizer3D_zoom;
int var8 = (viewportMouseX - centerX) * CLICKBOX_FAR / Rasterizer3D_zoom;
int var9 = (viewportMouseY - centerY) * CLICKBOX_FAR / Rasterizer3D_zoom;
int var10 = rl$rot1(var7, CLICKBOX_CLOSE, pitchCos, pitchSin);
int var11 = rl$rot2(var7, CLICKBOX_CLOSE, pitchCos, pitchSin);
var7 = var10;
var10 = rl$rot1(var9, CLICKBOX_FAR, pitchCos, pitchSin);
int var12 = rl$rot2(var9, CLICKBOX_FAR, pitchCos, pitchSin);
var9 = var10;
var10 = rl$rot3(var6, var11, yawCos, yawSin);
var11 = rl$rot4(var6, var11, yawCos, yawSin);
var6 = var10;
var10 = rl$rot3(var8, var12, yawCos, yawSin);
var12 = rl$rot4(var8, var12, yawCos, yawSin);
int field1720 = (var10 - var6) / 2;
int field638 = (var9 - var7) / 2;
int field1846 = (var12 - var11) / 2;
int field1722 = Math.abs(field1720);
int field601 = Math.abs(field638);
int field38 = Math.abs(field1846);
int var38 = x + model.getCenterX();
int var39 = y + model.getCenterY();
int var40 = z + model.getCenterZ();
int var41 = model.getExtremeX();
int var42 = model.getExtremeY();
int var43 = model.getExtremeZ();
int field1861 = (var6 + var10) / 2;
int field2317 = (var7 + var9) / 2;
int field528 = (var12 + var11) / 2;
int var44 = field1861 - var38;
int var45 = field2317 - var39;
int var46 = field528 - var40;
boolean passes;
if (Math.abs(var44) > var41 + field1722)
{
passes = false;
}
else if (Math.abs(var45) > var42 + field601)
{
passes = false;
}
else if (Math.abs(var46) > var43 + field38)
{
passes = false;
}
else if (Math.abs(var46 * field638 - var45 * field1846) > var42 * field38 + var43 * field601)
{
passes = false;
}
else if (Math.abs(var44 * field1846 - var46 * field1720) > var43 * field1722 + var41 * field38)
{
passes = false;
}
else if (Math.abs(var45 * field1720 - var44 * field638) > var42 * field1722 + var41 * field601)
{
passes = false;
}
else
{
passes = true;
}
return passes;
}
@Inject
private static int rl$rot1(int var0, int var1, int var2, int var3)
{
return var0 * var2 + var3 * var1 >> 16;
}
@Inject
private static int rl$rot2(int var0, int var1, int var2, int var3)
{
return var2 * var1 - var3 * var0 >> 16;
}
@Inject
private static int rl$rot3(int var0, int var1, int var2, int var3)
{
return var0 * var2 - var3 * var1 >> 16;
}
@Inject
private static int rl$rot4(int var0, int var1, int var2, int var3)
{
return var3 * var0 + var2 * var1 >> 16;
}
}

View File

@@ -87,6 +87,7 @@ import net.runelite.api.events.UsernameChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.hooks.Callbacks;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
@@ -124,6 +125,9 @@ public abstract class RSClientMixin implements RSClient
@javax.inject.Inject
private Callbacks callbacks;
@Inject
private DrawCallbacks drawCallbacks;
@Inject
@javax.inject.Inject
@Named("Core Logger")
@@ -156,6 +160,9 @@ public abstract class RSClientMixin implements RSClient
@Inject
private static RSItem lastItemDespawn;
@Inject
private boolean gpu;
@Inject
private static boolean oldIsResized;
@@ -166,6 +173,20 @@ public abstract class RSClientMixin implements RSClient
return callbacks;
}
@Inject
@Override
public DrawCallbacks getDrawCallbacks()
{
return drawCallbacks;
}
@Inject
@Override
public void setDrawCallbacks(DrawCallbacks drawCallbacks)
{
this.drawCallbacks = drawCallbacks;
}
@Inject
@Override
public Logger getLogger()
@@ -1277,6 +1298,20 @@ public abstract class RSClientMixin implements RSClient
RSClientMixin.lastItemDespawn = lastItemDespawn;
}
@Inject
@Override
public boolean isGpu()
{
return gpu;
}
@Inject
@Override
public void setGpu(boolean gpu)
{
this.gpu = gpu;
}
@Inject
@Override
public void queueChangedSkill(Skill skill)

View File

@@ -26,6 +26,8 @@ package net.runelite.mixins;
import java.awt.event.FocusEvent;
import net.runelite.api.events.FocusChanged;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin;
@@ -71,4 +73,27 @@ public abstract class RSGameEngineMixin implements RSGameEngine
focusChanged.setFocused(true);
client.getCallbacks().post(focusChanged);
}
@Inject
@MethodHook("post")
public void onPost(Object canvas)
{
DrawCallbacks drawCallbacks = client.getDrawCallbacks();
if (drawCallbacks != null)
{
drawCallbacks.draw();
}
}
@FieldHook("replaceCanvasNextFrame")
@Inject
public void onReplaceCanvasNextFrameChanged(int idx)
{
// when this is initially called the client instance doesn't exist yet
if (client != null && client.isGpu() && isReplaceCanvasNextFrame())
{
setReplaceCanvasNextFrame(false);
setResizeCanvasNextFrame(true);
}
}
}

View File

@@ -24,7 +24,17 @@
*/
package net.runelite.mixins;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.nio.IntBuffer;
import java.util.Hashtable;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
@@ -37,6 +47,30 @@ public abstract class RSMainBufferProviderMixin implements RSMainBufferProvider
@Shadow("clientInstance")
private static RSClient client;
@Inject
private IntBuffer buffer;
@MethodHook(value = "<init>", end = true)
@Inject
public void init(int width, int height, Component canvas)
{
if (!client.isGpu())
{
return;
}
final int[] pixels = getPixels();
// we need to make our own buffered image for the client with the alpha channel enabled in order to
// have alphas for the overlays applied correctly
DataBufferInt dataBufferInt = new DataBufferInt(pixels, pixels.length);
DirectColorModel directColorModel = new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000);
WritableRaster writableRaster = Raster.createWritableRaster(directColorModel.createCompatibleSampleModel(width, height), dataBufferInt, null);
BufferedImage bufferedImage = new BufferedImage(directColorModel, writableRaster, false, new Hashtable());
setImage(bufferedImage);
}
/**
* Replacing this method makes it so we can completely
* control when/what is drawn on the game's canvas,

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.Model;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSModel;
import net.runelite.rs.api.RSModelData;
@Mixin(RSModelData.class)
public abstract class RSModelDataMixin implements RSModelData
{
@Shadow("clientInstance")
private static RSClient client;
@Inject
private float[][] faceTextureUCoordinates;
@Inject
private float[][] faceTextureVCoordinates;
@Copy("light")
public abstract Model rs$light(int ambient, int contrast, int var3, int var4, int var5);
@Replace("light")
public Model rl$light(int ambient, int contrast, int var3, int var4, int var5)
{
client.getLogger().debug("Lighting model {}", this);
Model model = rs$light(ambient, contrast, var3, var4, var5);
if (model == null)
{
return null;
}
if (faceTextureUCoordinates == null)
{
computeTextureUVCoordinates();
}
RSModel rsModel = (RSModel) model;
rsModel.setFaceTextureUCoordinates(faceTextureUCoordinates);
rsModel.setFaceTextureVCoordinates(faceTextureVCoordinates);
return model;
}
@Inject
public void computeTextureUVCoordinates()
{
final short[] faceTextures = getFaceTextures();
if (faceTextures == null)
{
return;
}
final int[] vertexPositionsX = getVertexX();
final int[] vertexPositionsY = getVertexY();
final int[] vertexPositionsZ = getVertexZ();
final int[] trianglePointsX = getTrianglePointsX();
final int[] trianglePointsY = getTrianglePointsY();
final int[] trianglePointsZ = getTrianglePointsZ();
final short[] texTriangleX = getTexTriangleX();
final short[] texTriangleY = getTexTriangleY();
final short[] texTriangleZ = getTexTriangleZ();
final byte[] textureCoords = getTextureCoords();
final byte[] textureRenderTypes = getTextureRenderTypes();
int faceCount = getTriangleFaceCount();
this.faceTextureUCoordinates = new float[faceCount][];
this.faceTextureVCoordinates = new float[faceCount][];
for (int i = 0; i < faceCount; i++)
{
int textureCoordinate;
if (textureCoords == null)
{
textureCoordinate = -1;
}
else
{
textureCoordinate = textureCoords[i];
}
short textureIdx;
textureIdx = faceTextures[i];
if (textureIdx != -1)
{
float[] u = new float[3];
float[] v = new float[3];
if (textureCoordinate == -1)
{
u[0] = 0.0F;
v[0] = 1.0F;
u[1] = 1.0F;
v[1] = 1.0F;
u[2] = 0.0F;
v[2] = 0.0F;
}
else
{
textureCoordinate &= 0xFF;
byte textureRenderType = 0;
if (textureRenderTypes != null)
{
textureRenderType = textureRenderTypes[textureCoordinate];
}
if (textureRenderType == 0)
{
int faceVertexIdx1 = trianglePointsX[i];
int faceVertexIdx2 = trianglePointsY[i];
int faceVertexIdx3 = trianglePointsZ[i];
int triangleVertexIdx1 = texTriangleX[textureCoordinate];
int triangleVertexIdx2 = texTriangleY[textureCoordinate];
int triangleVertexIdx3 = texTriangleZ[textureCoordinate];
float triangleX = (float) vertexPositionsX[triangleVertexIdx1];
float triangleY = (float) vertexPositionsY[triangleVertexIdx1];
float triangleZ = (float) vertexPositionsZ[triangleVertexIdx1];
float f_882_ = (float) vertexPositionsX[triangleVertexIdx2] - triangleX;
float f_883_ = (float) vertexPositionsY[triangleVertexIdx2] - triangleY;
float f_884_ = (float) vertexPositionsZ[triangleVertexIdx2] - triangleZ;
float f_885_ = (float) vertexPositionsX[triangleVertexIdx3] - triangleX;
float f_886_ = (float) vertexPositionsY[triangleVertexIdx3] - triangleY;
float f_887_ = (float) vertexPositionsZ[triangleVertexIdx3] - triangleZ;
float f_888_ = (float) vertexPositionsX[faceVertexIdx1] - triangleX;
float f_889_ = (float) vertexPositionsY[faceVertexIdx1] - triangleY;
float f_890_ = (float) vertexPositionsZ[faceVertexIdx1] - triangleZ;
float f_891_ = (float) vertexPositionsX[faceVertexIdx2] - triangleX;
float f_892_ = (float) vertexPositionsY[faceVertexIdx2] - triangleY;
float f_893_ = (float) vertexPositionsZ[faceVertexIdx2] - triangleZ;
float f_894_ = (float) vertexPositionsX[faceVertexIdx3] - triangleX;
float f_895_ = (float) vertexPositionsY[faceVertexIdx3] - triangleY;
float f_896_ = (float) vertexPositionsZ[faceVertexIdx3] - triangleZ;
float f_897_ = f_883_ * f_887_ - f_884_ * f_886_;
float f_898_ = f_884_ * f_885_ - f_882_ * f_887_;
float f_899_ = f_882_ * f_886_ - f_883_ * f_885_;
float f_900_ = f_886_ * f_899_ - f_887_ * f_898_;
float f_901_ = f_887_ * f_897_ - f_885_ * f_899_;
float f_902_ = f_885_ * f_898_ - f_886_ * f_897_;
float f_903_ = 1.0F / (f_900_ * f_882_ + f_901_ * f_883_ + f_902_ * f_884_);
u[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_;
u[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_;
u[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_;
f_900_ = f_883_ * f_899_ - f_884_ * f_898_;
f_901_ = f_884_ * f_897_ - f_882_ * f_899_;
f_902_ = f_882_ * f_898_ - f_883_ * f_897_;
f_903_ = 1.0F / (f_900_ * f_885_ + f_901_ * f_886_ + f_902_ * f_887_);
v[0] = (f_900_ * f_888_ + f_901_ * f_889_ + f_902_ * f_890_) * f_903_;
v[1] = (f_900_ * f_891_ + f_901_ * f_892_ + f_902_ * f_893_) * f_903_;
v[2] = (f_900_ * f_894_ + f_901_ * f_895_ + f_902_ * f_896_) * f_903_;
}
}
this.faceTextureUCoordinates[i] = u;
this.faceTextureVCoordinates[i] = v;
}
}
}
}

View File

@@ -27,11 +27,15 @@ package net.runelite.mixins;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import net.runelite.api.Model;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Triangle;
@@ -48,6 +52,63 @@ public abstract class RSModelMixin implements RSModel
@Shadow("clientInstance")
private static RSClient client;
@Inject
private int rl$sceneId;
@Inject
private int rl$bufferOffset;
@Inject
private int rl$uvBufferOffset;
@Inject
private float[][] rl$faceTextureUCoordinates;
@Inject
private float[][] rl$faceTextureVCoordinates;
@MethodHook(value = "<init>", end = true)
@Inject
public void rl$init(RSModel[] models, int length)
{
int count = 0;
for (int i = 0; i < length; ++i)
{
RSModel model = models[i];
if (model != null)
{
count += model.getTrianglesCount();
}
}
float[][] u = new float[count][];
float[][] v = new float[count][];
int idx = 0;
for (int i = 0; i < length; ++i)
{
RSModel model = models[i];
if (model != null)
{
float[][] modelU = model.getFaceTextureUCoordinates();
float[][] modelV = model.getFaceTextureVCoordinates();
for (int j = 0; j < model.getTrianglesCount(); ++j)
{
if (modelU != null && modelV != null)
{
u[idx] = modelU[j];
v[idx] = modelV[j];
}
++idx;
}
}
}
setFaceTextureUCoordinates(u);
setFaceTextureVCoordinates(v);
}
@Override
@Inject
public List<Vertex> getVertices()
@@ -99,6 +160,33 @@ public abstract class RSModelMixin implements RSModel
return triangles;
}
@Copy("contourGround")
public abstract Model rs$contourGround(int[][] tileHeights, int packedX, int height, int packedY, boolean copy, int contouredGround);
@Replace("contourGround")
public Model rl$contourGround(int[][] tileHeights, int packedX, int height, int packedY, boolean copy, int contouredGround)
{
// With contouredGround >= 0 lighted models are countoured, so we need to copy uvs
Model model = rs$contourGround(tileHeights, packedX, height, packedY, copy, contouredGround);
if (model != null && model != this)
{
RSModel rsModel = (RSModel) model;
rsModel.setFaceTextureUCoordinates(rl$faceTextureUCoordinates);
rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates);
}
return model;
}
@MethodHook("buildSharedModel")
@Inject
public void rl$buildSharedModel(boolean refTransparencies, Model sharedModel, byte[] transparencyBuffer)
{
// Animated models are usually a shared Model instance that is global
RSModel rsModel = (RSModel) sharedModel;
rsModel.setFaceTextureUCoordinates(rl$faceTextureUCoordinates);
rsModel.setFaceTextureVCoordinates(rl$faceTextureVCoordinates);
}
@Inject
public void interpolateFrames(RSFrames frames, int frameId, RSFrames nextFrames, int nextFrameId, int interval,
int intervalCount)
@@ -277,4 +365,74 @@ public abstract class RSModelMixin implements RSModel
return p;
}
@Inject
@Override
public int getSceneId()
{
return rl$sceneId;
}
@Inject
@Override
public void setSceneId(int sceneId)
{
this.rl$sceneId = sceneId;
}
@Inject
@Override
public int getBufferOffset()
{
return rl$bufferOffset;
}
@Inject
@Override
public void setBufferOffset(int bufferOffset)
{
rl$bufferOffset = bufferOffset;
}
@Inject
@Override
public int getUvBufferOffset()
{
return rl$uvBufferOffset;
}
@Inject
@Override
public void setUvBufferOffset(int bufferOffset)
{
rl$uvBufferOffset = bufferOffset;
}
@Inject
@Override
public float[][] getFaceTextureUCoordinates()
{
return rl$faceTextureUCoordinates;
}
@Inject
@Override
public void setFaceTextureUCoordinates(float[][] faceTextureUCoordinates)
{
this.rl$faceTextureUCoordinates = faceTextureUCoordinates;
}
@Inject
@Override
public float[][] getFaceTextureVCoordinates()
{
return rl$faceTextureVCoordinates;
}
@Inject
@Override
public void setFaceTextureVCoordinates(float[][] faceTextureVCoordinates)
{
this.rl$faceTextureVCoordinates = faceTextureVCoordinates;
}
}

View File

@@ -26,9 +26,13 @@ package net.runelite.mixins;
import net.runelite.api.Perspective;
import net.runelite.api.Renderable;
import net.runelite.api.SceneTileModel;
import net.runelite.api.SceneTilePaint;
import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.hooks.DrawCallbacks;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
@@ -37,26 +41,45 @@ import net.runelite.rs.api.RSDecorativeObject;
import net.runelite.rs.api.RSGroundObject;
import net.runelite.rs.api.RSItemLayer;
import net.runelite.rs.api.RSScene;
import net.runelite.rs.api.RSSceneTileModel;
import net.runelite.rs.api.RSTile;
import net.runelite.rs.api.RSWallObject;
@Mixin(RSScene.class)
public abstract class RSSceneMixin implements RSScene
{
private static final int MAX_DISTANCE = 25;
private static final int DEFAULT_DISTANCE = 25;
private static final int MAX_DISTANCE = 90;
private static final int PITCH_LOWER_LIMIT = 128;
private static final int PITCH_UPPER_LIMIT = 383;
private static final int MAX_TARGET_DISTANCE = 45;
@Shadow("clientInstance")
private static RSClient client;
static RSClient client;
@Shadow("pitchRelaxEnabled")
private static boolean pitchRelaxEnabled;
@Inject
private static int[] tmpX = new int[6];
@Inject
private static int[] tmpY = new int[6];
@Inject
private static int rl$drawDistance;
@Replace("drawScene")
void rl$drawScene(int cameraX, int cameraY, int cameraZ, int cameraPitch, int cameraYaw, int plane)
{
final DrawCallbacks drawCallbacks = client.getDrawCallbacks();
if (drawCallbacks != null)
{
drawCallbacks.drawScene(cameraX, cameraY, cameraZ, cameraPitch, cameraYaw, plane);
}
final int maxX = getMaxX();
final int maxY = getMaxY();
final int maxZ = getMaxZ();
@@ -64,7 +87,8 @@ public abstract class RSSceneMixin implements RSScene
final int minLevel = getMinLevel();
final RSTile[][][] tiles = getTiles();
final int distance = MAX_DISTANCE;
final boolean isGpu = client.isGpu();
final int distance = isGpu ? rl$drawDistance : DEFAULT_DISTANCE;
if (cameraX < 0)
{
@@ -168,7 +192,8 @@ public abstract class RSSceneMixin implements RSScene
{
if (tile.getPhysicalLevel() <= plane
&& (renderArea[x - screenCenterX + MAX_DISTANCE][y - screenCenterZ + MAX_DISTANCE]
|| tileHeights[z][x][y] - cameraY >= 2000))
|| tileHeights[z][x][y] - cameraY >= 2000
|| isGpu))
{
tile.setDraw(true);
tile.setVisible(true);
@@ -402,13 +427,271 @@ public abstract class RSSceneMixin implements RSScene
@Replace("drawTileUnderlay")
public void rl$drawTileUnderlay(SceneTilePaint tile, int z, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y)
{
if (!client.isGpu())
{
try
{
rs$drawTileUnderlay(tile, z, pitchSin, pitchCos, yawSin, yawCos, x, y);
}
catch (Exception ex)
{
client.getLogger().warn("error during tile underlay rendering", ex);
}
return;
}
final DrawCallbacks drawCallbacks = client.getDrawCallbacks();
if (drawCallbacks == null)
{
return;
}
try
{
rs$drawTileUnderlay(tile, z, pitchSin, pitchCos, yawSin, yawCos, x, y);
final int[][][] tileHeights = getTileHeights();
final int cameraX2 = client.getCameraX2();
final int cameraY2 = client.getCameraY2();
final int cameraZ2 = client.getCameraZ2();
final int zoom = client.get3dZoom();
final int centerX = client.getCenterX();
final int centerY = client.getCenterY();
final int mouseX2 = client.getMouseX2();
final int mouseY2 = client.getMouseY2();
final boolean checkClick = client.isCheckClick();
int var9;
int var10 = var9 = (x << 7) - cameraX2;
int var11;
int var12 = var11 = (y << 7) - cameraZ2;
int var13;
int var14 = var13 = var10 + 128;
int var15;
int var16 = var15 = var12 + 128;
int var17 = tileHeights[z][x][y] - cameraY2;
int var18 = tileHeights[z][x + 1][y] - cameraY2;
int var19 = tileHeights[z][x + 1][y + 1] - cameraY2;
int var20 = tileHeights[z][x][y + 1] - cameraY2;
int var21 = var10 * yawCos + yawSin * var12 >> 16;
var12 = var12 * yawCos - yawSin * var10 >> 16;
var10 = var21;
var21 = var17 * pitchCos - pitchSin * var12 >> 16;
var12 = pitchSin * var17 + var12 * pitchCos >> 16;
var17 = var21;
if (var12 >= 50)
{
var21 = var14 * yawCos + yawSin * var11 >> 16;
var11 = var11 * yawCos - yawSin * var14 >> 16;
var14 = var21;
var21 = var18 * pitchCos - pitchSin * var11 >> 16;
var11 = pitchSin * var18 + var11 * pitchCos >> 16;
var18 = var21;
if (var11 >= 50)
{
var21 = var13 * yawCos + yawSin * var16 >> 16;
var16 = var16 * yawCos - yawSin * var13 >> 16;
var13 = var21;
var21 = var19 * pitchCos - pitchSin * var16 >> 16;
var16 = pitchSin * var19 + var16 * pitchCos >> 16;
var19 = var21;
if (var16 >= 50)
{
var21 = var9 * yawCos + yawSin * var15 >> 16;
var15 = var15 * yawCos - yawSin * var9 >> 16;
var9 = var21;
var21 = var20 * pitchCos - pitchSin * var15 >> 16;
var15 = pitchSin * var20 + var15 * pitchCos >> 16;
if (var15 >= 50)
{
int dy = var10 * zoom / var12 + centerX;
int dx = var17 * zoom / var12 + centerY;
int cy = var14 * zoom / var11 + centerX;
int cx = var18 * zoom / var11 + centerY;
int ay = var13 * zoom / var16 + centerX;
int ax = var19 * zoom / var16 + centerY;
int by = var9 * zoom / var15 + centerX;
int bx = var21 * zoom / var15 + centerY;
drawCallbacks.drawScenePaint(0, pitchSin, pitchCos, yawSin, yawCos,
-cameraX2, -cameraY2, -cameraZ2,
tile, z, x, y,
zoom, centerX, centerY);
if ((ay - by) * (cx - bx) - (ax - bx) * (cy - by) > 0)
{
if (checkClick && client.containsBounds(mouseX2, mouseY2, ax, bx, cx, ay, by, cy))
{
setTargetTile(x, y);
}
}
if ((dy - cy) * (bx - cx) - (dx - cx) * (by - cy) > 0)
{
if (checkClick && client.containsBounds(mouseX2, mouseY2, dx, cx, bx, dy, cy, by))
{
setTargetTile(x, y);
}
}
}
}
}
}
}
catch (Exception ex)
{
client.getLogger().warn("error during tile underlay rendering", ex);
client.getLogger().warn("error during underlay rendering", ex);
}
}
@Copy("drawTileOverlay")
abstract public void rs$drawTileOverlay(SceneTileModel tile, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y);
@Replace("drawTileOverlay")
public void rl$drawTileOverlay(SceneTileModel tile, int pitchSin, int pitchCos, int yawSin, int yawCos, int tileX, int tileY)
{
if (!client.isGpu())
{
rs$drawTileOverlay(tile, pitchSin, pitchCos, yawSin, yawCos, tileX, tileY);
return;
}
final DrawCallbacks drawCallbacks = client.getDrawCallbacks();
if (drawCallbacks == null)
{
return;
}
try
{
final int cameraX2 = client.getCameraX2();
final int cameraY2 = client.getCameraY2();
final int cameraZ2 = client.getCameraZ2();
final int zoom = client.get3dZoom();
final int centerX = client.getCenterX();
final int centerY = client.getCenterY();
drawCallbacks.drawSceneModel(0, pitchSin, pitchCos, yawSin, yawCos, -cameraX2, -cameraY2, -cameraZ2,
tile, client.getPlane(), tileX, tileY,
zoom, centerX, centerY);
final boolean checkClick = client.isCheckClick();
if (!checkClick)
{
return;
}
RSSceneTileModel sceneTileModel = (RSSceneTileModel) tile;
final int[] faceX = sceneTileModel.getFaceX();
final int[] faceY = sceneTileModel.getFaceY();
final int[] faceZ = sceneTileModel.getFaceZ();
final int[] vertexX = sceneTileModel.getVertexX();
final int[] vertexY = sceneTileModel.getVertexY();
final int[] vertexZ = sceneTileModel.getVertexZ();
final int vertexCount = vertexX.length;
final int faceCount = faceX.length;
final int mouseX2 = client.getMouseX2();
final int mouseY2 = client.getMouseY2();
for (int i = 0; i < vertexCount; ++i)
{
int vx = vertexX[i] - cameraX2;
int vy = vertexY[i] - cameraY2;
int vz = vertexZ[i] - cameraZ2;
int rotA = vz * yawSin + vx * yawCos >> 16;
int rotB = vz * yawCos - vx * yawSin >> 16;
int var13 = vy * pitchCos - rotB * pitchSin >> 16;
int var12 = vy * pitchSin + rotB * pitchCos >> 16;
if (var12 < 50)
{
return;
}
int ax = rotA * zoom / var12 + centerX;
int ay = var13 * zoom / var12 + centerY;
tmpX[i] = ax;
tmpY[i] = ay;
}
for (int i = 0; i < faceCount; ++i)
{
int va = faceX[i];
int vb = faceY[i];
int vc = faceZ[i];
int x1 = tmpX[va];
int x2 = tmpX[vb];
int x3 = tmpX[vc];
int y1 = tmpY[va];
int y2 = tmpY[vb];
int y3 = tmpY[vc];
if ((x1 - x2) * (y3 - y2) - (y1 - y2) * (x3 - x2) > 0)
{
if (client.containsBounds(mouseX2, mouseY2, y1, y2, y3, x1, x2, x3))
{
setTargetTile(tileX, tileY);
break;
}
}
}
}
catch (Exception ex)
{
client.getLogger().warn("error during overlay rendering", ex);
}
}
@Inject
@Override
public int getDrawDistance()
{
return rl$drawDistance;
}
@Inject
@Override
public void setDrawDistance(int drawDistance)
{
rl$drawDistance = drawDistance;
}
@Inject
static void setTargetTile(int targetX, int targetY)
{
final LocalPoint current = client.getLocalPlayer().getLocalLocation();
// Limit walk distance - https://math.stackexchange.com/a/85582
final int a = current.getSceneX();
final int b = current.getSceneY();
final int c = targetX;
final int d = targetY;
final int r = MAX_TARGET_DISTANCE;
final int t = (int) Math.hypot(a - c, b - d) - r;
int x = targetX;
int y = targetY;
if (t > 0)
{
x = (r * c + t * a) / (r + t);
y = (r * d + t * b) / (r + t);
}
client.setSelectedSceneTileX(x);
client.setSelectedSceneTileY(y);
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSSceneTileModel;
@Mixin(RSSceneTileModel.class)
public abstract class RSSceneTileModelMixin implements RSSceneTileModel
{
@Inject
private int rl$modelBufferOffset;
@Inject
private int rl$modelUvBufferOffset;
@Inject
private int rl$modelBufferLen;
@Inject
@Override
public int getBufferOffset()
{
return rl$modelBufferOffset;
}
@Inject
@Override
public void setBufferOffset(int bufferOffset)
{
rl$modelBufferOffset = bufferOffset;
}
@Inject
@Override
public int getUvBufferOffset()
{
return rl$modelUvBufferOffset;
}
@Inject
@Override
public void setUvBufferOffset(int bufferOffset)
{
rl$modelUvBufferOffset = bufferOffset;
}
@Inject
@Override
public int getBufferLen()
{
return rl$modelBufferLen;
}
@Inject
@Override
public void setBufferLen(int bufferLen)
{
rl$modelBufferLen = bufferLen;
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.rs.api.RSSceneTilePaint;
@Mixin(RSSceneTilePaint.class)
public abstract class RSSceneTilePaintMixin implements RSSceneTilePaint
{
@Inject
private int rl$paintModelBufferOffset;
@Inject
private int rl$paintModelUvBufferOffset;
@Inject
private int rl$paintModelBufferLen;
@Inject
@Override
public int getBufferOffset()
{
return rl$paintModelBufferOffset;
}
@Inject
@Override
public void setBufferOffset(int bufferOffset)
{
rl$paintModelBufferOffset = bufferOffset;
}
@Inject
@Override
public int getUvBufferOffset()
{
return rl$paintModelUvBufferOffset;
}
@Inject
@Override
public void setUvBufferOffset(int bufferOffset)
{
rl$paintModelUvBufferOffset = bufferOffset;
}
@Inject
@Override
public int getBufferLen()
{
return rl$paintModelBufferLen;
}
@Inject
@Override
public void setBufferLen(int bufferLen)
{
rl$paintModelBufferLen = bufferLen;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSTexture;
@Mixin(RSTexture.class)
public abstract class RSTextureMixin implements RSTexture
{
@Shadow("clientInstance")
private static RSClient client;
@Inject
private float rl$u;
@Inject
private float rl$v;
@Copy("animate")
public abstract void rs$animate(int diff);
@Replace("animate")
public void rl$animate(int diff)
{
// The client animates textures by cycling the backing pixels of the texture each fram
// based on how long it was since the last tick. On GPU we let the plugin manage this
// which will calculate uvs instead.
if (!client.isGpu())
{
rs$animate(diff);
return;
}
client.getDrawCallbacks().animate(this, diff);
}
@Inject
@Override
public float getU()
{
return rl$u;
}
@Inject
@Override
public void setU(float u)
{
this.rl$u = u;
}
@Inject
@Override
public float getV()
{
return rl$v;
}
@Inject
@Override
public void setV(float v)
{
this.rl$v = v;
}
}

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.mixins;
import net.runelite.api.IndexDataBase;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.MethodHook;
import net.runelite.api.mixins.Mixin;
@@ -37,9 +38,20 @@ public abstract class RSTextureProviderMixin implements RSTextureProvider
@Shadow("clientInstance")
private static RSClient client;
@MethodHook(value = "<init>", end = true)
@Inject
public void rl$init(IndexDataBase indexTextures, IndexDataBase indexSprites, int maxSize, double brightness, int width)
{
// the client's max size is 20, however there are many scenes with >20 textures,
// which causes continuous alloc/free of textures with the gl. There are
// only ~57 textures in total.
setMaxSize(64);
setSize(64);
}
@MethodHook(value = "checkTextures", end = true)
public void checkTextures(int var1)
@Inject
public void checkTextures(int diff)
{
client.getCallbacks().drawAboveOverheads();
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
@Mixin(RSClient.class)
public abstract class Rasterizer2DMixin implements RSClient
{
@Shadow("clientInstance")
private static RSClient client;
@Inject
private static void drawAlpha(int[] pixels, int index, int value, int color, int alpha)
{
if (!client.isGpu() || pixels != client.getBufferProvider().getPixels())
{
pixels[index] = value;
return;
}
if (alpha == 0)
{
return;
}
int prevColor = pixels[index];
if ((prevColor & 0xFF000000) == 0 || alpha == 255)
{
// No transparency, so we can cheat to save CPU resources
pixels[index] = (color & 0xFFFFFF) | (alpha << 24);
return;
}
if ((prevColor & 0xFF000000) == 0xFF000000)
{
// When the background is opaque, the result will also be opaque,
// so we can simply use the value calculated by Jagex.
pixels[index] = value | 0xFF000000;
return;
}
int prevAlpha = (prevColor >>> 24) * (255 - alpha) >>> 8;
int finalAlpha = alpha + prevAlpha;
// Scale alphas so (relativeAlpha >>> 8) is approximately equal to (alpha / finalAlpha).
// Avoiding extra divisions increase performance by quite a bit.
// And with divisions we get a problems if dividing a number where
// the last bit is 1 (as it will become negative).
int relativeAlpha1 = (alpha << 8) / finalAlpha;
int relativeAlpha2 = (prevAlpha << 8) / finalAlpha;
// Red and blue are calculated at the same time to save CPU cycles
int finalColor =
(((color & 0xFF00FF) * relativeAlpha1 + (prevColor & 0xFF00FF) * relativeAlpha2 & 0xFF00FF00) |
((color & 0x00FF00) * relativeAlpha1 + (prevColor & 0x00FF00) * relativeAlpha2 & 0x00FF0000)) >>> 8;
pixels[index] = finalColor | (finalAlpha << 24);
}
@Copy("drawGradientAlpha")
private static void rs$raster2d6(int var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7)
{
throw new RuntimeException();
}
@Replace("drawGradientAlpha")
private static void rl$drawGradientAlpha(int var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7)
{
final int width = client.getGraphicsPixelsWidth();
final int startX = client.getStartX();
final int startY = client.getStartY();
final int endX = client.getEndX();
final int endY = client.getEndY();
final int[] pixels = client.getGraphicsPixels();
if (!client.isGpu())
{
rs$raster2d6(var0, var1, var2, var3, var4, var5, var6, var7);
return;
}
if (var2 > 0 && var3 > 0)
{
int var8 = 0;
int var9 = 65536 / var3;
if (var0 < startX)
{
var2 -= startX - var0;
var0 = startX;
}
if (var1 < startY)
{
var8 += (startY - var1) * var9;
var3 -= startY - var1;
var1 = startY;
}
if (var0 + var2 > endX)
{
var2 = endX - var0;
}
if (var3 + var1 > endY)
{
var3 = endY - var1;
}
int var10 = width - var2;
int var11 = var0 + width * var1;
for (int var12 = -var3; var12 < 0; ++var12)
{
int var13 = 65536 - var8 >> 8;
int var14 = var8 >> 8;
int var15 = (var13 * var6 + var14 * var7 & 65280) >>> 8;
if (var15 == 0)
{
var11 += width;
var8 += var9;
}
else
{
int var16 = (var14 * (var5 & 16711935) + var13 * (var4 & 16711935) & -16711936) + (var14 * (var5 & 65280) + var13 * (var4 & 65280) & 16711680) >>> 8;
for (int var19 = -var2; var19 < 0; ++var19)
{
drawAlpha(pixels, var11++, 0, var16, var15);
}
var11 += var10;
var8 += var9;
}
}
}
}
@Copy("raster2d7")
public static void rs$raster2d7(int var0, int var1, int var2, int var3, int var4, int var5, byte[] var6, int var7)
{
throw new RuntimeException();
}
@Replace("raster2d7")
public static void rl$raster2d7(int var0, int var1, int var2, int var3, int var4, int var5, byte[] var6, int var7)
{
final int width = client.getGraphicsPixelsWidth();
final int height = client.getGraphicsPixelsHeight();
final int[] pixels = client.getGraphicsPixels();
if (!client.isGpu())
{
rs$raster2d7(var0, var1, var2, var3, var4, var5, var6, var7);
return;
}
if (var0 + var2 >= 0 && var3 + var1 >= 0)
{
if (var0 < width && var1 < height)
{
int var8 = 0;
int var9 = 0;
if (var0 < 0)
{
var8 -= var0;
var2 += var0;
}
if (var1 < 0)
{
var9 -= var1;
var3 += var1;
}
if (var0 + var2 > width)
{
var2 = width - var0;
}
if (var3 + var1 > height)
{
var3 = height - var1;
}
int var10 = var6.length / var7;
int var11 = width - var2;
int var12 = var4 >>> 24;
int var13 = var5 >>> 24;
int var14;
int var15;
int var16;
int var17;
int var18;
if (var12 == 255 && var13 == 255)
{
var14 = var0 + var8 + (var9 + var1) * width;
for (var15 = var9 + var1; var15 < var3 + var9 + var1; ++var15)
{
for (var16 = var0 + var8; var16 < var0 + var8 + var2; ++var16)
{
var17 = (var15 - var1) % var10;
var18 = (var16 - var0) % var7;
if (var6[var18 + var17 * var7] != 0)
{
pixels[var14++] = var5;
}
else
{
pixels[var14++] = var4;
}
}
var14 += var11;
}
}
else
{
var14 = var0 + var8 + (var9 + var1) * width;
for (var15 = var9 + var1; var15 < var3 + var9 + var1; ++var15)
{
for (var16 = var0 + var8; var16 < var0 + var8 + var2; ++var16)
{
var17 = (var15 - var1) % var10;
var18 = (var16 - var0) % var7;
int var19 = var4;
if (var6[var18 + var17 * var7] != 0)
{
var19 = var5;
}
int var20 = var19 >>> 24;
drawAlpha(pixels, var14++, 0, var19, var20);
}
var14 += var11;
}
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.mixins;
import net.runelite.api.coords.LocalPoint;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSPlayer;
import org.junit.Test;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class RSSceneMixinTest
{
@Test
public void testWalkDistance()
{
RSClient client = mock(RSClient.class);
RSPlayer localPlayer = mock(RSPlayer.class);
when(client.getLocalPlayer()).thenReturn(localPlayer);
when(localPlayer.getLocalLocation()).thenReturn(new LocalPoint(0, 0));
RSSceneMixin.client = client;
RSSceneMixin.setTargetTile(90, 0);
verify(client).setSelectedSceneTileX(eq(45));
verify(client).setSelectedSceneTileY(eq(0));
}
}

View File

@@ -26,7 +26,7 @@ package net.runelite.rs.api;
import net.runelite.mapping.Import;
public interface RSBuffer
public interface RSBuffer extends RSNode
{
@Import("payload")
byte[] getPayload();

View File

@@ -29,6 +29,18 @@ import net.runelite.mapping.Import;
public interface RSBufferProvider extends BufferProvider
{
@Import("pixels")
@Override
int[] getPixels();
@Import("width")
@Override
int getWidth();
@Import("height")
@Override
int getHeight();
@Import("setRaster")
void setRaster();
}

View File

@@ -48,6 +48,18 @@ public interface RSClient extends RSGameEngine, Client
@Override
int getCameraZ();
@Import("cameraX2")
@Override
int getCameraX2();
@Import("cameraY2")
@Override
int getCameraY2();
@Import("cameraZ2")
@Override
int getCameraZ2();
@Import("plane")
@Override
int getPlane();
@@ -146,9 +158,15 @@ public interface RSClient extends RSGameEngine, Client
@Import("selectedSceneTileX")
int getSelectedSceneTileX();
@Import("selectedSceneTileX")
void setSelectedSceneTileX(int selectedSceneTileX);
@Import("selectedSceneTileY")
int getSelectedSceneTileY();
@Import("selectedSceneTileY")
void setSelectedSceneTileY(int selectedSceneTileY);
@Import("draggingWidget")
@Override
boolean isDraggingWidget();
@@ -246,6 +264,18 @@ public interface RSClient extends RSGameEngine, Client
@Import("mouseY")
int getMouseY();
@Import("mouseX2")
int getMouseX2();
@Import("mouseY2")
int getMouseY2();
@Import("containsBounds")
boolean containsBounds(int var0, int var1, int var2, int var3, int var4, int var5, int var6, int var7);
@Import("checkClick")
boolean isCheckClick();
@Import("menuOptionCount")
int getMenuOptionCount();
@@ -289,6 +319,14 @@ public interface RSClient extends RSGameEngine, Client
@Override
int getScale();
@Import("canvasHeight")
@Override
int getCanvasHeight();
@Import("canvasWidth")
@Override
int getCanvasWidth();
@Import("viewportHeight")
@Override
int getViewportHeight();
@@ -565,11 +603,36 @@ public interface RSClient extends RSGameEngine, Client
void setYawCos(int v);
@Import("Rasterizer3D_zoom")
@Override
int get3dZoom();
@Import("Rasterizer3D_zoom")
void set3dZoom(int zoom);
@Import("Rasterizer3D_clipMidX2")
@Override
int getRasterizer3D_clipMidX2();
@Import("Rasterizer3D_clipNegativeMidX")
@Override
int getRasterizer3D_clipNegativeMidX();
@Import("Rasterizer3D_clipNegativeMidY")
@Override
int getRasterizer3D_clipNegativeMidY();
@Import("Rasterizer3D_clipMidY2")
@Override
int getRasterizer3D_clipMidY2();
@Import("centerX")
@Override
int getCenterX();
@Import("centerY")
@Override
int getCenterY();
@Import("renderOverview")
RSRenderOverview getRenderOverview();
@@ -664,6 +727,10 @@ public interface RSClient extends RSGameEngine, Client
@Override
RSNodeCache getWidgetSpriteCache();
@Import("oculusOrbState")
@Override
int getOculusOrbState();
@Import("oculusOrbState")
@Override
void setOculusOrbState(int state);
@@ -689,9 +756,31 @@ public interface RSClient extends RSGameEngine, Client
@Protect
void menuAction(int var0, int var1, int var2, int var3, String var4, String var5, int var6, int var7);
@Import("Viewport_entityCountAtMouse")
int getEntitiesAtMouseCount();
@Import("Viewport_entityCountAtMouse")
void setEntitiesAtMouseCount(int i);
@Import("Viewport_entitiesAtMouse")
long[] getEntitiesAtMouse();
@Import("Viewport_mouseX")
int getViewportMouseX();
@Import("Viewport_mouseY")
int getViewportMouseY();
@Import("textureProvider")
@Override
RSTextureProvider getTextureProvider();
@Import("occupiedTilesTick")
int[][] getOccupiedTilesTick();
@Import("cachedModels2")
RSNodeCache getCachedModels2();
@Import("cycle")
int getCycle();
@@ -739,4 +828,28 @@ public interface RSClient extends RSGameEngine, Client
@Import("tileUpdateCount")
void setTileUpdateCount(int tileUpdateCount);
@Import("Viewport_containsMouse")
boolean getViewportContainsMouse();
@Import("graphicsPixels")
int[] getGraphicsPixels();
@Import("graphicsPixelsWidth")
int getGraphicsPixelsWidth();
@Import("graphicsPixelsHeight")
int getGraphicsPixelsHeight();
@Import("startX")
int getStartX();
@Import("startY")
int getStartY();
@Import("endX")
int getEndX();
@Import("endY")
int getEndY();
}

View File

@@ -43,7 +43,12 @@ public interface RSDecorativeObject extends DecorativeObject
int getOrientation();
@Import("renderable1")
@Override
RSRenderable getRenderable();
@Import("renderable2")
@Override
RSRenderable getRenderable2();
void setPlane(int plane);
}

View File

@@ -33,6 +33,22 @@ public interface RSGameEngine extends GameEngine
@Import("canvas")
Canvas getCanvas();
@Import("post")
void post(Object canvas);
@Import("resizeCanvas")
@Override
void resizeCanvas();
@Import("resizeCanvasNextFrame")
void setResizeCanvasNextFrame(boolean state);
boolean isResizeCanvasNextFrame();
@Import("resizeCanvasNextFrame")
void setResizeCanvasNextFrame(boolean resize);
@Import("replaceCanvasNextFrame")
boolean isReplaceCanvasNextFrame();
@Import("replaceCanvasNextFrame")
void setReplaceCanvasNextFrame(boolean replace);
}

View File

@@ -25,7 +25,6 @@
package net.runelite.rs.api;
import net.runelite.api.GroundObject;
import net.runelite.api.Renderable;
import net.runelite.mapping.Import;
public interface RSGroundObject extends GroundObject
@@ -41,7 +40,8 @@ public interface RSGroundObject extends GroundObject
int getY();
@Import("renderable")
Renderable getRenderable();
@Override
RSRenderable getRenderable();
void setPlane(int plane);
}

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.rs.api;
import java.awt.Component;
import java.awt.Image;
import net.runelite.api.MainBufferProvider;
import net.runelite.mapping.Import;
@@ -33,4 +34,10 @@ public interface RSMainBufferProvider extends RSBufferProvider, MainBufferProvid
@Import("image")
@Override
Image getImage();
@Import("image")
void setImage(Image image);
@Import("canvas")
Component getCanvas();
}

View File

@@ -31,35 +31,75 @@ import net.runelite.mapping.Import;
public interface RSModel extends RSRenderable, Model
{
@Import("verticesCount")
@Override
int getVerticesCount();
@Import("verticesX")
@Override
int[] getVerticesX();
@Import("verticesY")
@Override
int[] getVerticesY();
@Import("verticesZ")
@Override
int[] getVerticesZ();
@Import("indicesCount")
@Override
int getTrianglesCount();
@Import("indices1")
@Override
int[] getTrianglesX();
@Import("indices2")
@Override
int[] getTrianglesY();
@Import("indices3")
@Override
int[] getTrianglesZ();
@Import("faceColors1")
@Override
int[] getFaceColors1();
@Import("faceColors2")
@Override
int[] getFaceColors2();
@Import("faceColors3")
@Override
int[] getFaceColors3();
@Import("triangleTransparencies")
@Override
byte[] getTriangleTransparencies();
@Import("faceRenderPriorities")
@Override
byte[] getFaceRenderPriorities();
@Import("vertexGroups")
int[][] getVertexGroups();
@Import("modelHeight")
@Override
int getModelHeight();
@Import("animate")
void animate(int type, int[] list, int x, int y, int z);
@Import("calculateBoundsCylinder")
@Override
void calculateBoundsCylinder();
@Import("calculateExtreme")
@Override
void calculateExtreme(int orientation);
@Import("resetBounds")
void resetBounds();
@@ -78,6 +118,45 @@ public interface RSModel extends RSRenderable, Model
@Import("rotateY270Ccw")
void rotateY270Ccw();
@Import("isClickable")
boolean isClickable();
@Import("radius")
@Override
int getRadius();
@Import("centerX")
@Override
int getCenterX();
@Import("centerY")
@Override
int getCenterY();
@Import("centerZ")
@Override
int getCenterZ();
@Import("extremeX")
@Override
int getExtremeX();
@Import("extremeY")
@Override
int getExtremeY();
@Import("extremeZ")
@Override
int getExtremeZ();
@Import("faceTextures")
@Override
short[] getFaceTextures();
@Import("XYZMag")
@Override
int getXYZMag();
void interpolateFrames(RSFrames frames, int frameId, RSFrames nextFrames, int nextFrameId, int interval,
int intervalCount);
@@ -89,4 +168,10 @@ public interface RSModel extends RSRenderable, Model
* @return
*/
Polygon getConvexHull(int localX, int localY, int orientation);
float[][] getFaceTextureUCoordinates();
void setFaceTextureUCoordinates(float[][] rl$faceTextureUCoordinates);
float[][] getFaceTextureVCoordinates();
void setFaceTextureVCoordinates(float[][] rl$faceTextureVCoordinates);
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.rs.api;
import net.runelite.mapping.Import;
public interface RSModelData extends RSRenderable
{
@Import("triangleFaceCount")
int getTriangleFaceCount();
@Import("trianglePointsX")
int[] getTrianglePointsX();
@Import("trianglePointsY")
int[] getTrianglePointsY();
@Import("trianglePointsZ")
int[] getTrianglePointsZ();
@Import("vertexX")
int[] getVertexX();
@Import("vertexY")
int[] getVertexY();
@Import("vertexZ")
int[] getVertexZ();
@Import("texTriangleX")
short[] getTexTriangleX();
@Import("texTriangleY")
short[] getTexTriangleY();
@Import("texTriangleZ")
short[] getTexTriangleZ();
@Import("faceTextures")
short[] getFaceTextures();
@Import("textureCoords")
byte[] getTextureCoords();
@Import("textureRenderTypes")
byte[] getTextureRenderTypes();
}

View File

@@ -33,5 +33,14 @@ public interface RSNodeCache extends NodeCache
RSCacheableNode get(long id);
@Import("reset")
@Override
void reset();
@Import("capacity")
@Override
void setCapacity(int capacity);
@Import("remainingCapacity")
@Override
void setRemainingCapacity(int remainingCapacity);
}

View File

@@ -32,7 +32,15 @@ public interface RSRenderable extends RSNode, Renderable
@Import("modelHeight")
int getModelHeight();
@Import("modelHeight")
@Override
void setModelHeight(int modelHeight);
@Import("getModel")
@Override
RSModel getModel();
@Import("draw")
@Override
void draw(int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash);
}

View File

@@ -40,6 +40,9 @@ public interface RSScene extends Scene
@Import("draw")
void draw(Tile tile, boolean var2);
@Import("tileHeights")
int[][][] getTileHeights();
@Import("drawTile")
void drawTile(int[] pixels, int pixelOffset, int width, int z, int x, int y);

View File

@@ -44,4 +44,44 @@ public interface RSSceneTileModel extends SceneTileModel
@Import("rotation")
@Override
int getRotation();
@Import("faceX")
@Override
int[] getFaceX();
@Import("faceY")
@Override
int[] getFaceY();
@Import("faceZ")
@Override
int[] getFaceZ();
@Import("vertexX")
@Override
int[] getVertexX();
@Import("vertexY")
@Override
int[] getVertexY();
@Import("vertexZ")
@Override
int[] getVertexZ();
@Import("triangleColorA")
@Override
int[] getTriangleColorA();
@Import("triangleColorB")
@Override
int[] getTriangleColorB();
@Import("triangleColorC")
@Override
int[] getTriangleColorC();
@Import("triangleTextureId")
@Override
int[] getTriangleTextureId();
}

View File

@@ -32,4 +32,24 @@ public interface RSSceneTilePaint extends SceneTilePaint
@Import("rgb")
@Override
int getRBG();
@Import("swColor")
@Override
int getSwColor();
@Import("seColor")
@Override
int getSeColor();
@Import("nwColor")
@Override
int getNwColor();
@Import("neColor")
@Override
int getNeColor();
@Import("texture")
@Override
int getTexture();
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. 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.
*
* 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.
*/
package net.runelite.rs.api;
import net.runelite.api.Texture;
import net.runelite.mapping.Import;
public interface RSTexture extends Texture, RSNode
{
@Import("pixels")
@Override
int[] getPixels();
@Import("animationDirection")
@Override
int getAnimationDirection();
@Import("animationSpeed")
@Override
int getAnimationSpeed();
@Import("loaded")
@Override
boolean isLoaded();
}

View File

@@ -29,7 +29,25 @@ import net.runelite.mapping.Import;
public interface RSTextureProvider extends TextureProvider
{
@Import("brightness")
@Override
@Import("checkTextures")
void checkTextures(int var1);
double getBrightness();
@Import("setBrightness")
@Override
void setBrightness(double brightness);
@Import("maxSize")
void setMaxSize(int maxSize);
@Import("size")
void setSize(int size);
@Import("textures")
@Override
RSTexture[] getTextures();
@Import("load")
@Override
int[] load(int textureId);
}

View File

@@ -74,9 +74,20 @@ public interface RSTile extends Tile
@Override
int getPlane();
@Import("renderLevel")
@Override
int getRenderLevel();
@Import("physicalLevel")
int getPhysicalLevel();
@Import("flags")
int getFlags();
@Import("bridge")
@Override
RSTile getBridge();
@Import("draw")
boolean isDraw();
@@ -89,9 +100,6 @@ public interface RSTile extends Tile
@Import("visible")
void setVisible(boolean visible);
@Import("drawEntities")
boolean isDrawEntities();
@Import("drawEntities")
void setDrawEntities(boolean drawEntities);

View File

@@ -24,7 +24,6 @@
*/
package net.runelite.rs.api;
import net.runelite.api.Renderable;
import net.runelite.api.WallObject;
import net.runelite.mapping.Import;
@@ -51,10 +50,12 @@ public interface RSWallObject extends WallObject
int getOrientationB();
@Import("renderable1")
Renderable getRenderable1();
@Override
RSRenderable getRenderable1();
@Import("renderable2")
Renderable getRenderable2();
@Override
RSRenderable getRenderable2();
@Import("config")
@Override