import java.io.{BufferedReader, InputStreamReader}
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.OpenGlHelper
import net.minecraft.client.renderer.texture.{TextureManager, TextureUtil}
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.ARBShaderObjects._
import org.lwjgl.opengl.GL11.{GL_DEPTH_COMPONENT, GL_TEXTURE_2D, glBindTexture}
import org.lwjgl.opengl._
import ru.justagod.ogl.render.shader.ShaderException
/**
* Created by JustAGod on 20.01.2018.
*/
object OGLHelper {
def bindItemsTexture(): Unit = {
val manager = Minecraft.getMinecraft.renderEngine
manager.bindTexture(manager.getResourceLocation(1))
}
def bindBlocksTexture(): Unit = {
val manager = Minecraft.getMinecraft.renderEngine
manager.bindTexture(manager.getResourceLocation(0))
}
def createProgram(vertex: Option[ResourceLocation], fragment: Option[ResourceLocation], geometric: Option[ResourceLocation] = None): Int = {
val program = glCreateProgramObjectARB()
if (program == 0) throw new ShaderException("Can't create program")
if (vertex.nonEmpty) {
val vertexShader = loadShader(ARBVertexShader.GL_VERTEX_SHADER_ARB, loadShader(vertex.get))
glAttachObjectARB(program, vertexShader)
}
if (fragment.nonEmpty) {
val fragmentShader = loadShader(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB, loadShader(fragment.get))
glAttachObjectARB(program, fragmentShader)
}
// TODO: Разобраться с геометрическими шейдерами
/*if (geometric.nonEmpty) {
val fragmentShader = loadShader(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB, loadShader(fragment.get))
glAttachObjectARB(program, fragmentShader)
}*/
glLinkProgramARB(program)
if (glGetObjectParameteriARB(program, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
val log = getLogInfo(program)
glDeleteObjectARB(program)
throw new ShaderException(s"Can't link program. \n$log")
}
program
}
def createProgramI(vertex: Option[Int], fragment: Option[Int], geometric: Option[Int] = None): Int = {
val program = glCreateProgramObjectARB()
if (program == 0) throw new ShaderException("Can't create program")
if (vertex.nonEmpty) {
glAttachObjectARB(program, vertex.get)
}
if (fragment.nonEmpty) {
glAttachObjectARB(program, fragment.get)
}
// TODO: Разобраться с геометрическими шейдерами
/*if (geometric.nonEmpty) {
val fragmentShader = loadShader(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB, loadShader(fragment.get))
glAttachObjectARB(program, fragmentShader)
}*/
glLinkProgramARB(program)
if (glGetObjectParameteriARB(program, GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
val log = getLogInfo(program)
glDeleteObjectARB(program)
throw new ShaderException(s"Can't link program. \n$log")
}
program
}
def checkObject(obj: Int): Int = if (obj == 0) throw new RuntimeException("Not valid OpenGL object" ) else obj
def framebufferStatus: Int = {
checkFbo()
OpenGlHelper.func_153167_i(GL30.GL_FRAMEBUFFER)
}
def loadShader(enum: Int, name: ResourceLocation): Int = loadShader(enum, loadShader(name))
def loadShader(enum: Int, source: String): Int = {
val shader = glCreateShaderObjectARB(enum)
if (shader == 0) {
throw new ShaderException("Can't create shader")
}
glShaderSourceARB(shader, source)
glCompileShaderARB(shader)
if (glGetObjectParameteriARB(shader, GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) {
val log = getLogInfo(shader)
glDeleteObjectARB(shader)
throw new ShaderException(s"Can't compile shader. \n$log")
}
shader
}
def loadShader(name: ResourceLocation): String = {
val in = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft.mcResourceManager.getResource(name).getInputStream))
val builder = new StringBuilder
while (in.ready()) {
builder.append(in.readLine()).append('\n')
}
builder.toString()
}
def deleteFramebuffer(fbo: Int): Unit = {
checkFbo()
OpenGlHelper.func_153174_h(fbo)
}
def deleteRenderBuffer(buffer: Int): Unit = {
checkFbo()
OpenGlHelper.func_153184_g(buffer)
}
def deleteTexture(texture: Int): Unit = TextureUtil.deleteTexture(texture)
def fboSupported: Boolean = OpenGlHelper.framebufferSupported
def createFbo(): Int = {
checkFbo()
OpenGlHelper.func_153165_e
}
def bindFbo(fbo: Int): Unit = {
checkFbo()
glBindTexture(GL_TEXTURE_2D, 0)
OpenGlHelper.func_153171_g(OpenGlHelper.field_153198_e, fbo)
}
def unbindFbo(): Unit = {
checkFbo()
if (OpenGlHelper.isFramebufferEnabled) {
Minecraft.getMinecraft.getFramebuffer.bindFramebuffer(false)
} else {
OpenGlHelper.func_153171_g(OpenGlHelper.field_153198_e, 0)
}
}
def bindFboTexture(fbo: Int, texture: Int): Unit = {
checkFbo()
OpenGlHelper.func_153188_a(OpenGlHelper.field_153198_e, OpenGlHelper.field_153200_g, GL11.GL_TEXTURE_2D, texture, 0)
}
def createRenderBuffer(): Int = {
checkFbo()
OpenGlHelper.func_153185_f
}
def bindRenderBuffer(buffer: Int): Unit = {
checkFbo()
OpenGlHelper.func_153176_h(OpenGlHelper.field_153199_f, buffer)
}
def framebufferRenderBuffer(buffer: Int): Unit = {
checkFbo()
OpenGlHelper.func_153190_b(OpenGlHelper.field_153198_e, OpenGlHelper.field_153201_h, OpenGlHelper.field_153199_f, buffer)
}
def renderBufferStorage(width: Int, height: Int): Unit = {
checkFbo()
OpenGlHelper.func_153186_a(OpenGlHelper.field_153199_f, GL_DEPTH_COMPONENT, width, height)
}
private def checkFbo(): Unit = if (!fboSupported) throw new RuntimeException("Frame buffers not supported")
private def getLogInfo(obj: Int) = glGetInfoLogARB(obj, glGetObjectParameteriARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB))
}