
de.lessvoid.nifty.renderer.lwjgl.render.LwjglRenderDevice Maven / Gradle / Ivy
package de.lessvoid.nifty.renderer.lwjgl.render;
import de.lessvoid.nifty.render.BlendMode;
import de.lessvoid.nifty.spi.render.MouseCursor;
import de.lessvoid.nifty.spi.render.RenderDevice;
import de.lessvoid.nifty.spi.render.RenderFont;
import de.lessvoid.nifty.spi.render.RenderImage;
import de.lessvoid.nifty.spi.time.TimeProvider;
import de.lessvoid.nifty.spi.time.impl.AccurateTimeProvider;
import de.lessvoid.nifty.tools.Color;
import de.lessvoid.nifty.tools.resourceloader.NiftyResourceLoader;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import java.io.IOException;
import java.nio.IntBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Lwjgl RenderDevice Implementation.
*
* @author void
*
* @deprecated Use {@link de.lessvoid.nifty.render.batch.BatchRenderDevice} with either
* {@link LwjglBatchRenderBackendFactory#create()} or {@link LwjglBatchRenderBackendCoreProfileFactory#create()}.
*/
@Deprecated
public class LwjglRenderDevice implements RenderDevice {
private static final Logger log = Logger.getLogger(LwjglRenderDevice.class.getName());
private static final IntBuffer viewportBuffer = BufferUtils.createIntBuffer(4 * 4);
private final TimeProvider timeProvider = new AccurateTimeProvider();
private NiftyResourceLoader resourceLoader;
private int viewportWidth = -1;
private int viewportHeight = -1;
private long time;
private long frames;
private boolean displayFPS = false;
private boolean logFPS = false;
private RenderFont fpsFont;
// we keep track of which GL states we've already set to make sure we don't set
// the same state twice.
private boolean currentTexturing = true;
@Nullable
private BlendMode currentBlendMode = null;
private boolean currentClipping = false;
private int currentClippingX0 = 0;
private int currentClippingY0 = 0;
private int currentClippingX1 = 0;
private int currentClippingY1 = 0;
@Nonnull
private StringBuilder buffer = new StringBuilder();
private int quadCount;
private int glyphCount;
@Nullable
private MouseCursor mouseCursor;
/**
* The standard constructor. You'll use this in production code. Using this
* constructor will configure the RenderDevice to not log FPS on System.out.
*/
public LwjglRenderDevice() {
time = timeProvider.getMsTime();
frames = 0;
}
/**
* The development mode constructor allows to display the FPS on screen when
* the given flag is set to true. Note that setting displayFPS to false will
* still log the FPS on System.out every couple of frames.
*/
public LwjglRenderDevice(final boolean displayFPS) {
this();
this.logFPS = true;
this.displayFPS = displayFPS;
}
@Override
public void setResourceLoader(@Nonnull final NiftyResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
if (this.displayFPS) {
fpsFont = createFont("fps.fnt");
}
}
/**
* Get Width.
*
* @return width of display mode
*/
@Override
public int getWidth() {
if (viewportWidth == -1) {
getViewport();
}
return viewportWidth;
}
/**
* Get Height.
*
* @return height of display mode
*/
@Override
public int getHeight() {
if (viewportHeight == -1) {
getViewport();
}
return viewportHeight;
}
private void getViewport() {
GL11.glGetInteger(GL11.GL_VIEWPORT, viewportBuffer);
viewportWidth = viewportBuffer.get(2);
viewportHeight = viewportBuffer.get(3);
if (log.isLoggable(Level.FINE)) {
log.fine("Viewport: " + viewportWidth + ", " + viewportHeight);
}
}
@Override
public void beginFrame() {
log.fine("beginFrame()");
// set inital states for each frame
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
setBlendMode(BlendMode.BLEND);
GL11.glEnable(GL11.GL_TEXTURE_2D);
currentTexturing = true;
GL11.glDisable(GL11.GL_SCISSOR_TEST);
currentClipping = false;
currentClippingX0 = 0;
currentClippingY0 = 0;
currentClippingX1 = 0;
currentClippingY1 = 0;
quadCount = 0;
glyphCount = 0;
}
@Override
public void endFrame() {
log.fine("endFrame");
frames++;
long diff = timeProvider.getMsTime() - time;
if (diff >= 1000) {
time += diff;
long lastFrames = frames;
buffer.setLength(0);
buffer.append("FPS: ");
buffer.append(lastFrames);
buffer.append(" (");
buffer.append(String.format("%f", 1000.f / lastFrames));
buffer.append(" ms)");
buffer.append(", Total Tri: ");
buffer.append(quadCount * 2);
buffer.append(" (Text: ");
buffer.append(glyphCount * 2);
buffer.append(")");
buffer.append(", Total Vert: ");
buffer.append(quadCount * 4);
buffer.append(" (Text: ");
buffer.append(glyphCount * 4);
buffer.append(")");
if (logFPS) {
System.out.println(buffer.toString());
}
frames = 0;
}
if (displayFPS) {
renderFont(fpsFont, buffer.toString(), 10, getHeight() - fpsFont.getHeight() - 10, Color.WHITE, 1.0f, 1.0f);
}
// currently the RenderDevice interface does not support a way to be notified when the resolution is changed
// so we reset the viewportWidth and viewportHeight here so that we only call getViewport() once per frame and
// not each time someone calls getWidth() or getHeight().
viewportWidth = -1;
viewportHeight = -1;
checkGLError();
}
@Override
public void clear() {
log.fine("clear()");
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
}
/**
* Create a new RenderImage.
*
* @param filename filename
* @param filterLinear linear filter the image
* @return RenderImage
*/
@Override
@Nonnull
public RenderImage createImage(@Nonnull final String filename, final boolean filterLinear) {
return new LwjglRenderImage(filename, filterLinear, resourceLoader);
}
/**
* Create a new RenderFont.
*
* @param filename filename
* @return RenderFont
*/
@Override
@Nonnull
public RenderFont createFont(@Nonnull final String filename) {
return new LwjglRenderFont(filename, resourceLoader);
}
/**
* Render a quad.
*
* @param x x
* @param y y
* @param width width
* @param height height
* @param color color
*/
@Override
public void renderQuad(final int x, final int y, final int width, final int height, @Nonnull final Color color) {
log.fine("renderQuad()");
if (currentTexturing) {
GL11.glDisable(GL11.GL_TEXTURE_2D);
currentTexturing = false;
}
GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2i(x, y);
GL11.glVertex2i(x + width, y);
GL11.glVertex2i(x + width, y + height);
GL11.glVertex2i(x, y + height);
GL11.glEnd();
quadCount++;
}
@Override
public void renderQuad(
final int x,
final int y,
final int width,
final int height,
@Nonnull final Color topLeft,
@Nonnull final Color topRight,
@Nonnull final Color bottomRight,
@Nonnull final Color bottomLeft) {
log.fine("renderQuad2()");
if (currentTexturing) {
GL11.glDisable(GL11.GL_TEXTURE_2D);
currentTexturing = false;
}
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor4f(topLeft.getRed(), topLeft.getGreen(), topLeft.getBlue(), topLeft.getAlpha());
GL11.glVertex2i(x, y);
GL11.glColor4f(topRight.getRed(), topRight.getGreen(), topRight.getBlue(), topRight.getAlpha());
GL11.glVertex2i(x + width, y);
GL11.glColor4f(bottomRight.getRed(), bottomRight.getGreen(), bottomRight.getBlue(), bottomRight.getAlpha());
GL11.glVertex2i(x + width, y + height);
GL11.glColor4f(bottomLeft.getRed(), bottomLeft.getGreen(), bottomLeft.getBlue(), bottomLeft.getAlpha());
GL11.glVertex2i(x, y + height);
GL11.glEnd();
quadCount++;
}
/**
* Render the image using the given Box to specify the render attributes.
*
* @param x x
* @param y y
* @param width width
* @param height height
* @param color color
* @param scale scale
*/
@Override
public void renderImage(
@Nonnull final RenderImage image,
final int x,
final int y,
final int width,
final int height,
@Nonnull final Color color,
final float scale) {
log.fine("renderImage()");
if (width < 0) {
log.warning("Attempt to render image with negative width");
return;
}
if (height < 0) {
log.warning("Attempt to render image with negative height");
return;
}
if (!currentTexturing) {
GL11.glEnable(GL11.GL_TEXTURE_2D);
currentTexturing = true;
}
GL11.glPushMatrix();
GL11.glTranslatef(x + width / 2, y + height / 2, 0.0f);
GL11.glScalef(scale, scale, 1.0f);
GL11.glTranslatef(-(x + width / 2), -(y + height / 2), 0.0f);
LwjglRenderImage internalImage = (LwjglRenderImage) image;
internalImage.bind();
float textureWidth = (float) internalImage.getTextureWidth();
float textureHeight = (float) internalImage.getTextureHeight();
float imageWidth = (float) internalImage.getWidth();
float imageHeight = (float) internalImage.getHeight();
float u1 = imageWidth / textureWidth;
float v1 = imageHeight / textureHeight;
GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2i(x, y);
GL11.glTexCoord2f(u1, 0.0f);
GL11.glVertex2i(x + width, y);
GL11.glTexCoord2f(u1, v1);
GL11.glVertex2i(x + width, y + height);
GL11.glTexCoord2f(0.0f, v1);
GL11.glVertex2i(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();
quadCount++;
}
/**
* Render sub image.
*
* @param x x
* @param y y
* @param w w
* @param h h
* @param srcX x
* @param srcY y
* @param srcW w
* @param srcH h
* @param color color
*/
@Override
public void renderImage(
@Nonnull final RenderImage image,
final int x,
final int y,
final int w,
final int h,
final int srcX,
final int srcY,
final int srcW,
final int srcH,
@Nonnull final Color color,
final float scale,
final int centerX,
final int centerY) {
log.fine("renderImage2()");
if (w < 0) {
log.warning("Attempt to render image with negative width");
return;
}
if (h < 0) {
log.warning("Attempt to render image with negative height");
return;
}
if (!currentTexturing) {
GL11.glEnable(GL11.GL_TEXTURE_2D);
currentTexturing = true;
}
GL11.glPushMatrix();
GL11.glTranslatef(centerX, centerY, 0.0f);
GL11.glScalef(scale, scale, 1.0f);
GL11.glTranslatef(-(centerX), -(centerY), 0.0f);
LwjglRenderImage internalImage = (LwjglRenderImage) image;
internalImage.bind();
float textureWidth = (float) internalImage.getTextureWidth();
float textureHeight = (float) internalImage.getTextureHeight();
float u0 = srcX / textureWidth;
float v0 = srcY / textureHeight;
float u1 = (srcX + srcW) / textureWidth;
float v1 = (srcY + srcH) / textureHeight;
GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(u0, v0);
GL11.glVertex2i(x, y);
GL11.glTexCoord2f(u1, v0);
GL11.glVertex2i(x + w, y);
GL11.glTexCoord2f(u1, v1);
GL11.glVertex2i(x + w, y + h);
GL11.glTexCoord2f(u0, v1);
GL11.glVertex2i(x, y + h);
GL11.glEnd();
GL11.glPopMatrix();
quadCount++;
}
/**
* render the text.
*/
@Override
public void renderFont(
@Nonnull final RenderFont font,
@Nonnull final String text,
final int x,
final int y,
@Nonnull final Color color,
final float fontSizeX,
final float fontSizeY) {
log.fine("renderFont()");
if (!currentTexturing) {
GL11.glEnable(GL11.GL_TEXTURE_2D);
currentTexturing = true;
}
setBlendMode(BlendMode.BLEND);
int count = ((LwjglRenderFont) font).getFont().renderWithSizeAndColor(x, y, text, fontSizeX, fontSizeY,
color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
glyphCount += count;
quadCount += count;
}
private void checkGLError() {
int error = GL11.glGetError();
if (error != GL11.GL_NO_ERROR) {
String glerrmsg = GLU.gluErrorString(error);
log.warning("Error: (" + error + ") " + glerrmsg);
try {
throw new Exception();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Enable clipping to the given region.
*
* @param x0 x0
* @param y0 y0
* @param x1 x1
* @param y1 y1
*/
@Override
public void enableClip(final int x0, final int y0, final int x1, final int y1) {
log.fine("enableClip()");
if (currentClipping && currentClippingX0 == x0 && currentClippingY0 == y0 && currentClippingX1 == x1 &&
currentClippingY1 == y1) {
return;
}
currentClipping = true;
currentClippingX0 = x0;
currentClippingY0 = y0;
currentClippingX1 = x1;
currentClippingY1 = y1;
GL11.glScissor(x0, getHeight() - y1, x1 - x0, y1 - y0);
GL11.glEnable(GL11.GL_SCISSOR_TEST);
}
/**
* Disable Clip.
*/
@Override
public void disableClip() {
log.fine("disableClip()");
if (!currentClipping) {
return;
}
GL11.glDisable(GL11.GL_SCISSOR_TEST);
currentClipping = false;
currentClippingX0 = 0;
currentClippingY0 = 0;
currentClippingX1 = 0;
currentClippingY1 = 0;
}
@Override
public void setBlendMode(@Nonnull final BlendMode renderMode) {
log.fine("setBlendMode()");
if (renderMode.equals(currentBlendMode)) {
return;
}
currentBlendMode = renderMode;
if (currentBlendMode.equals(BlendMode.BLEND)) {
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
} else if (currentBlendMode.equals(BlendMode.MULIPLY)) {
GL11.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_ZERO);
}
}
@Override
@Nonnull
public MouseCursor createMouseCursor(
@Nonnull final String filename,
final int hotspotX,
final int hotspotY) throws IOException {
return new LwjglMouseCursor(filename, hotspotX, hotspotY, resourceLoader);
}
@Override
public void enableMouseCursor(@Nonnull final MouseCursor mouseCursor) {
this.mouseCursor = mouseCursor;
mouseCursor.enable();
}
@Override
public void disableMouseCursor() {
if (mouseCursor != null) {
mouseCursor.disable();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy