gpu: add option to disable compute shaders

This still gives a noticible performance boost over software rendering
as the rasterizing is entirely done on GPU
This commit is contained in:
Adam
2020-04-20 10:30:50 -04:00
parent fe1772031a
commit 035c119f85
3 changed files with 233 additions and 72 deletions

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.client.plugins.gpu;
import com.google.common.primitives.Ints;
import com.google.inject.Provides;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.JAWTWindow;
@@ -74,7 +75,17 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginInstantiationException;
import net.runelite.client.plugins.PluginManager;
import static net.runelite.client.plugins.gpu.GLUtil.*;
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteBuffer;
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteFrameBuffer;
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteRenderbuffers;
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteTexture;
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteVertexArrays;
import static net.runelite.client.plugins.gpu.GLUtil.glGenBuffers;
import static net.runelite.client.plugins.gpu.GLUtil.glGenFrameBuffer;
import static net.runelite.client.plugins.gpu.GLUtil.glGenRenderbuffer;
import static net.runelite.client.plugins.gpu.GLUtil.glGenTexture;
import static net.runelite.client.plugins.gpu.GLUtil.glGenVertexArrays;
import static net.runelite.client.plugins.gpu.GLUtil.glGetInteger;
import net.runelite.client.plugins.gpu.config.AntiAliasingMode;
import net.runelite.client.plugins.gpu.config.UIScalingMode;
import net.runelite.client.plugins.gpu.template.Template;
@@ -94,6 +105,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private static final int MAX_TRIANGLE = 4096;
private static final int SMALL_TRIANGLE_COUNT = 512;
private static final int FLAG_SCENE_BUFFER = Integer.MIN_VALUE;
private static final int DEFAULT_DISTANCE = 25;
static final int MAX_DISTANCE = 90;
static final int MAX_FOG_DEPTH = 100;
@@ -118,6 +130,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Inject
private PluginManager pluginManager;
private boolean useComputeShaders;
private Canvas canvas;
private JAWTWindow jawtWindow;
private GL4 gl;
@@ -231,6 +245,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private int centerY;
private int yaw;
private int pitch;
// fields for non-compute draw
private boolean drawingModel;
private int modelX, modelY, modelZ;
private int modelOrientation;
// Uniforms
private int uniUseFog;
@@ -259,6 +277,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
{
bufferId = uvBufferId = uniformBufferId = tmpBufferId = tmpUvBufferId = tmpModelBufferId = tmpModelBufferSmallId = tmpModelBufferUnorderedId = tmpOutBufferId = tmpOutUvBufferId = -1;
unorderedModels = smallModels = largeModels = 0;
drawingModel = false;
canvas = client.getCanvas();
@@ -267,6 +286,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
return false;
}
useComputeShaders = config.useComputeShaders();
canvas.setIgnoreRepaint(true);
vertexBuffer = new GpuIntBuffer();
@@ -461,11 +482,15 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
template.addInclude(GpuPlugin.class);
glProgram = PROGRAM.compile(gl, template);
glComputeProgram = COMPUTE_PROGRAM.compile(gl, template);
glSmallComputeProgram = SMALL_COMPUTE_PROGRAM.compile(gl, template);
glUnorderedComputeProgram = UNORDERED_COMPUTE_PROGRAM.compile(gl, template);
glUiProgram = UI_PROGRAM.compile(gl, template);
if (useComputeShaders)
{
glComputeProgram = COMPUTE_PROGRAM.compile(gl, template);
glSmallComputeProgram = SMALL_COMPUTE_PROGRAM.compile(gl, template);
glUnorderedComputeProgram = UNORDERED_COMPUTE_PROGRAM.compile(gl, template);
}
initUniforms();
}
@@ -738,8 +763,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
pitch = client.getCameraPitch();
final Scene scene = client.getScene();
final int drawDistance = Math.max(0, Math.min(MAX_DISTANCE, config.drawDistance()));
scene.setDrawDistance(drawDistance);
scene.setDrawDistance(getDrawDistance());
}
@Override
@@ -747,7 +771,17 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
SceneTilePaint paint, int tileZ, int tileX, int tileY,
int zoom, int centerX, int centerY)
{
if (paint.getBufferLen() > 0)
if (!useComputeShaders)
{
targetBufferOffset += sceneUploader.upload(paint,
tileZ, tileX, tileY,
vertexBuffer, uvBuffer,
Perspective.LOCAL_TILE_SIZE * tileX,
Perspective.LOCAL_TILE_SIZE * tileY,
true
);
}
else if (paint.getBufferLen() > 0)
{
x = tileX * Perspective.LOCAL_TILE_SIZE;
y = 0;
@@ -774,7 +808,14 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
SceneTileModel model, int tileZ, int tileX, int tileY,
int zoom, int centerX, int centerY)
{
if (model.getBufferLen() > 0)
if (!useComputeShaders)
{
targetBufferOffset += sceneUploader.upload(model,
tileX, tileY,
vertexBuffer, uvBuffer,
tileX << Perspective.LOCAL_COORD_BITS, tileY << Perspective.LOCAL_COORD_BITS, true);
}
else if (model.getBufferLen() > 0)
{
x = tileX * Perspective.LOCAL_TILE_SIZE;
y = 0;
@@ -913,7 +954,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
null,
gl.GL_STREAM_DRAW);
// UBO
// UBO. Only the first 32 bytes get modified here, the rest is the constant sin/cos table.
gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, uniformBufferId);
uniformBuffer.clear();
uniformBuffer
@@ -930,60 +971,63 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glBufferSubData(gl.GL_UNIFORM_BUFFER, 0, uniformBuffer.limit() * Integer.BYTES, uniformBuffer);
gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0);
gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, 0, uniformBufferId);
// Draw 3d scene
final TextureProvider textureProvider = client.getTextureProvider();
if (textureProvider != null)
{
gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0);
gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0);
if (useComputeShaders)
{
gl.glUniformBlockBinding(glSmallComputeProgram, uniBlockSmall, 0);
gl.glUniformBlockBinding(glComputeProgram, uniBlockLarge, 0);
gl.glBindBufferBase(gl.GL_UNIFORM_BUFFER, 0, uniformBufferId);
/*
* Compute is split into two separate programs 'small' and 'large' to
* save on GPU resources. Small will sort <= 512 faces, large will do <= 4096.
*/
/*
* Compute is split into two separate programs 'small' and 'large' to
* save on GPU resources. Small will sort <= 512 faces, large will do <= 4096.
*/
// unordered
gl.glUseProgram(glUnorderedComputeProgram);
// unordered
gl.glUseProgram(glUnorderedComputeProgram);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnorderedId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferUnorderedId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glDispatchCompute(unorderedModels, 1, 1);
gl.glDispatchCompute(unorderedModels, 1, 1);
// small
gl.glUseProgram(glSmallComputeProgram);
// small
gl.glUseProgram(glSmallComputeProgram);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmallId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferSmallId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glDispatchCompute(smallModels, 1, 1);
gl.glDispatchCompute(smallModels, 1, 1);
// large
gl.glUseProgram(glComputeProgram);
// large
gl.glUseProgram(glComputeProgram);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 0, tmpModelBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 1, this.bufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 2, tmpBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 3, tmpOutBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 4, tmpOutUvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 5, this.uvBufferId);
gl.glBindBufferBase(gl.GL_SHADER_STORAGE_BUFFER, 6, tmpUvBufferId);
gl.glDispatchCompute(largeModels, 1, 1);
gl.glDispatchCompute(largeModels, 1, 1);
gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT);
gl.glMemoryBarrier(gl.GL_SHADER_STORAGE_BARRIER_BIT);
}
if (textureArrayId == -1)
{
@@ -1023,7 +1067,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glUseProgram(glProgram);
final int drawDistance = Math.max(0, Math.min(MAX_DISTANCE, config.drawDistance()));
final int drawDistance = getDrawDistance();
final int fogDepth = config.fogDepth();
gl.glUniform1i(uniUseFog, fogDepth > 0 ? 1 : 0);
gl.glUniform4f(uniFogColor, (sky >> 16 & 0xFF) / 255f, (sky >> 8 & 0xFF) / 255f, (sky & 0xFF) / 255f, 1f);
@@ -1061,15 +1105,17 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glEnable(gl.GL_BLEND);
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA);
// Draw output of compute shaders
// Draw buffers
gl.glBindVertexArray(vaoHandle);
// When using compute shaders, draw using the output buffer of the compute. Otherwise
// only use the temporary buffers, which will contain the full scene.
gl.glEnableVertexAttribArray(0);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutBufferId);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, useComputeShaders ? tmpOutBufferId : tmpBufferId);
gl.glVertexAttribIPointer(0, 4, gl.GL_INT, 0, 0);
gl.glEnableVertexAttribArray(1);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, tmpOutUvBufferId);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, useComputeShaders ? tmpOutUvBufferId : tmpUvBufferId);
gl.glVertexAttribPointer(1, 4, gl.GL_FLOAT, false, 0, 0);
gl.glDrawArrays(gl.GL_TRIANGLES, 0, targetBufferOffset);
@@ -1236,7 +1282,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
if (gameStateChanged.getGameState() != GameState.LOGGED_IN)
if (!useComputeShaders || gameStateChanged.getGameState() != GameState.LOGGED_IN)
{
return;
}
@@ -1328,8 +1374,38 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Override
public void draw(Renderable renderable, int orientation, int pitchSin, int pitchCos, int yawSin, int yawCos, int x, int y, int z, long hash)
{
if (!useComputeShaders)
{
Model model = renderable instanceof Model ? (Model) renderable : renderable.getModel();
if (model != null)
{
model.calculateBoundsCylinder();
model.calculateExtreme(orientation);
if (!isVisible(model, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash))
{
return;
}
client.checkClickbox(model, orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
modelX = x + client.getCameraX2();
modelY = y + client.getCameraY2();
modelZ = z + client.getCameraZ2();
modelOrientation = orientation;
int triangleCount = model.getTrianglesCount();
vertexBuffer.ensureCapacity(12 * triangleCount);
uvBuffer.ensureCapacity(12 * triangleCount);
drawingModel = true;
renderable.draw(orientation, pitchSin, pitchCos, yawSin, yawCos, x, y, z, hash);
drawingModel = false;
}
}
// Model may be in the scene buffer
if (renderable instanceof Model && ((Model) renderable).getSceneId() == sceneUploader.sceneId)
else if (renderable instanceof Model && ((Model) renderable).getSceneId() == sceneUploader.sceneId)
{
Model model = (Model) renderable;
@@ -1386,7 +1462,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
int len = 0;
for (int i = 0; i < faces; ++i)
{
len += sceneUploader.pushFace(model, i, vertexBuffer, uvBuffer);
len += sceneUploader.pushFace(model, i, false, vertexBuffer, uvBuffer, 0, 0, 0, 0);
}
GpuIntBuffer b = bufferForTriangles(faces);
@@ -1411,6 +1487,18 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
}
}
@Override
public boolean drawFace(Model model, int face)
{
if (!drawingModel)
{
return false;
}
targetBufferOffset += sceneUploader.pushFace(model, face, true, vertexBuffer, uvBuffer, modelX, modelY, modelZ, modelOrientation);
return true;
}
/**
* returns the correct buffer based on triangle count and updates model count
*
@@ -1445,4 +1533,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
getScaledValue(t.getScaleX(), width),
getScaledValue(t.getScaleY(), height));
}
private int getDrawDistance()
{
final int limit = useComputeShaders ? MAX_DISTANCE : DEFAULT_DISTANCE;
return Ints.constrainToRange(config.drawDistance(), 0, limit);
}
}

View File

@@ -96,4 +96,15 @@ public interface GpuPluginConfig extends Config
{
return 0;
}
@ConfigItem(
keyName = "useComputeShaders",
name = "Compute Shaders",
description = "Offloads face sorting to GPU, enabling extended draw distance. Requires plugin restart.",
position = 6
)
default boolean useComputeShaders()
{
return true;
}
}

View File

@@ -176,7 +176,10 @@ class SceneUploader
sceneTilePaint.setUvBufferOffset(-1);
}
Point tilePoint = tile.getSceneLocation();
int len = upload(sceneTilePaint, tile.getRenderLevel(), tilePoint.getX(), tilePoint.getY(), vertexBuffer, uvBuffer);
int len = upload(sceneTilePaint,
tile.getRenderLevel(), tilePoint.getX(), tilePoint.getY(),
vertexBuffer, uvBuffer,
0, 0, false);
sceneTilePaint.setBufferLen(len);
offset += len;
if (sceneTilePaint.getTexture() != -1)
@@ -198,7 +201,10 @@ class SceneUploader
sceneTileModel.setUvBufferOffset(-1);
}
Point tilePoint = tile.getSceneLocation();
int len = upload(sceneTileModel, tilePoint.getX(), tilePoint.getY(), vertexBuffer, uvBuffer);
int len = upload(sceneTileModel,
tilePoint.getX(), tilePoint.getY(),
vertexBuffer, uvBuffer,
0, 0, false);
sceneTileModel.setBufferLen(len);
offset += len;
if (sceneTileModel.getTriangleTextureId() != null)
@@ -265,12 +271,13 @@ class SceneUploader
}
}
private int upload(SceneTilePaint tile, int tileZ, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
int upload(SceneTilePaint tile, int tileZ, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer,
int offsetX, int offsetY, boolean padUvs)
{
final int[][][] tileHeights = client.getTileHeights();
final int localX = 0;
final int localY = 0;
final int localX = offsetX;
final int localY = offsetY;
int swHeight = tileHeights[tileZ][tileX][tileY];
int seHeight = tileHeights[tileZ][tileX + 1][tileY];
@@ -322,7 +329,7 @@ class SceneUploader
vertexBuffer.put(vertexCx, vertexCz, vertexCy, c2);
vertexBuffer.put(vertexBx, vertexBz, vertexBy, c4);
if (tile.getTexture() != -1)
if (padUvs || tile.getTexture() != -1)
{
float tex = tile.getTexture() + 1f;
uvBuffer.put(tex, 1.0f, 1.0f, 0f);
@@ -337,7 +344,8 @@ class SceneUploader
return 6;
}
private int upload(SceneTileModel sceneTileModel, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
int upload(SceneTileModel sceneTileModel, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer,
int offsetX, int offsetY, boolean padUvs)
{
final int[] faceX = sceneTileModel.getFaceX();
final int[] faceY = sceneTileModel.getFaceY();
@@ -379,6 +387,7 @@ class SceneUploader
cnt += 3;
// vertexes are stored in scene local, convert to tile local
int vertexXA = vertexX[triangleA] - baseX;
int vertexZA = vertexZ[triangleA] - baseY;
@@ -388,13 +397,13 @@ class SceneUploader
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);
vertexBuffer.put(vertexXA + offsetX, vertexY[triangleA], vertexZA + offsetY, colorA);
vertexBuffer.put(vertexXB + offsetX, vertexY[triangleB], vertexZB + offsetY, colorB);
vertexBuffer.put(vertexXC + offsetX, vertexY[triangleC], vertexZC + offsetY, colorC);
if (triangleTextures != null)
if (padUvs || triangleTextures != null)
{
if (triangleTextures[i] != -1)
if (triangleTextures != null && triangleTextures[i] != -1)
{
float tex = triangleTextures[i] + 1f;
uvBuffer.put(tex, vertexXA / 128f, vertexZA / 128f, 0f);
@@ -438,7 +447,7 @@ class SceneUploader
int len = 0;
for (int i = 0; i < triangleCount; ++i)
{
len += pushFace(model, i, vertexBuffer, uvBuffer);
len += pushFace(model, i, false, vertexBuffer, uvBuffer, 0, 0, 0, 0);
}
offset += len;
@@ -448,7 +457,8 @@ class SceneUploader
}
}
int pushFace(Model model, int face, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
int pushFace(Model model, int face, boolean padUvs, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer,
int xOffset, int yOffset, int zOffset, int orientation)
{
final int[] vertexX = model.getVerticesX();
final int[] vertexY = model.getVerticesY();
@@ -485,6 +495,13 @@ class SceneUploader
priority = (facePriorities[face] & 0xff) << 16;
}
int sin = 0, cos = 0;
if (orientation != 0)
{
sin = Perspective.SINE[orientation];
cos = Perspective.COSINE[orientation];
}
if (color3 == -1)
{
color2 = color3 = color1;
@@ -495,7 +512,7 @@ class SceneUploader
vertexBuffer.put(0, 0, 0, 0);
vertexBuffer.put(0, 0, 0, 0);
if (faceTextures != null)
if (padUvs || faceTextures != null)
{
uvBuffer.put(0, 0, 0, 0f);
uvBuffer.put(0, 0, 0, 0f);
@@ -510,26 +527,65 @@ class SceneUploader
b = vertexY[triangleA];
c = vertexZ[triangleA];
if (orientation != 0)
{
int x = c * sin + a * cos >> 16;
int z = c * cos - a * sin >> 16;
a = x;
c = z;
}
a += xOffset;
b += yOffset;
c += zOffset;
vertexBuffer.put(a, b, c, alpha | priority | color1);
a = vertexX[triangleB];
b = vertexY[triangleB];
c = vertexZ[triangleB];
if (orientation != 0)
{
int x = c * sin + a * cos >> 16;
int z = c * cos - a * sin >> 16;
a = x;
c = z;
}
a += xOffset;
b += yOffset;
c += zOffset;
vertexBuffer.put(a, b, c, alpha | priority | color2);
a = vertexX[triangleC];
b = vertexY[triangleC];
c = vertexZ[triangleC];
if (orientation != 0)
{
int x = c * sin + a * cos >> 16;
int z = c * cos - a * sin >> 16;
a = x;
c = z;
}
a += xOffset;
b += yOffset;
c += zOffset;
vertexBuffer.put(a, b, c, alpha | priority | color3);
float[][] u = model.getFaceTextureUCoordinates();
float[][] v = model.getFaceTextureVCoordinates();
float[] uf, vf;
if (faceTextures != null)
if (padUvs || faceTextures != null)
{
if (u != null && v != null && (uf = u[face]) != null && (vf = v[face]) != null)
if (faceTextures != null && u != null && v != null && (uf = u[face]) != null && (vf = v[face]) != null)
{
float texture = faceTextures[face] + 1f;
uvBuffer.put(texture, uf[0], vf[0], 0f);