Add GPU renderer
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user