200 lines
7.7 KiB
Haxe
200 lines
7.7 KiB
Haxe
|
package kha.graphics4;
|
||
|
|
||
|
import js.html.webgl.GL;
|
||
|
import haxe.io.Bytes;
|
||
|
import kha.js.graphics4.Graphics;
|
||
|
|
||
|
class CubeMap implements Canvas implements Resource {
|
||
|
var myWidth: Int;
|
||
|
var myHeight: Int;
|
||
|
var format: TextureFormat;
|
||
|
var renderTarget: Bool;
|
||
|
var depthStencilFormat: DepthStencilFormat;
|
||
|
var graphics4: kha.graphics4.Graphics;
|
||
|
|
||
|
public var frameBuffer: Dynamic = null;
|
||
|
public var texture: Dynamic = null;
|
||
|
public var depthTexture: Dynamic = null;
|
||
|
public var isDepthAttachment: Bool = false;
|
||
|
|
||
|
// WebGL2 constants
|
||
|
static inline var GL_RGBA16F = 0x881A;
|
||
|
static inline var GL_RGBA32F = 0x8814;
|
||
|
static inline var GL_R16F = 0x822D;
|
||
|
static inline var GL_R32F = 0x822E;
|
||
|
static inline var GL_DEPTH_COMPONENT24 = 0x81A6;
|
||
|
static inline var GL_DEPTH24_STENCIL8 = 0x88F0;
|
||
|
static inline var GL_DEPTH32F_STENCIL8 = 0x8CAD;
|
||
|
|
||
|
function new(size: Int, format: TextureFormat, renderTarget: Bool, depthStencilFormat: DepthStencilFormat) {
|
||
|
myWidth = size;
|
||
|
myHeight = size;
|
||
|
this.format = format;
|
||
|
this.renderTarget = renderTarget;
|
||
|
this.depthStencilFormat = depthStencilFormat;
|
||
|
if (renderTarget)
|
||
|
createTexture();
|
||
|
}
|
||
|
|
||
|
public static function createRenderTarget(size: Int, format: TextureFormat = null, depthStencil: DepthStencilFormat = null): CubeMap {
|
||
|
if (format == null)
|
||
|
format = TextureFormat.RGBA32;
|
||
|
if (depthStencil == null)
|
||
|
depthStencil = NoDepthAndStencil;
|
||
|
return new CubeMap(size, format, true, depthStencil);
|
||
|
}
|
||
|
|
||
|
function createTexture() {
|
||
|
if (SystemImpl.gl == null)
|
||
|
return;
|
||
|
|
||
|
texture = SystemImpl.gl.createTexture();
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture);
|
||
|
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.LINEAR);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.LINEAR);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
|
||
|
|
||
|
if (renderTarget) {
|
||
|
frameBuffer = SystemImpl.gl.createFramebuffer();
|
||
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer);
|
||
|
|
||
|
switch (format) {
|
||
|
case DEPTH16:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, myWidth,
|
||
|
myHeight, 0, GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null);
|
||
|
case RGBA128:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_RGBA32F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA,
|
||
|
GL.FLOAT, null);
|
||
|
case RGBA64:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_RGBA16F : GL.RGBA, myWidth, myHeight, 0, GL.RGBA,
|
||
|
SystemImpl.halfFloat.HALF_FLOAT_OES, null);
|
||
|
case RGBA32:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null);
|
||
|
case A32:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_R32F : GL.ALPHA, myWidth, myHeight, 0, GL.ALPHA,
|
||
|
GL.FLOAT, null);
|
||
|
case A16:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, SystemImpl.gl2 ? GL_R16F : GL.ALPHA, myWidth, myHeight, 0, GL.ALPHA,
|
||
|
SystemImpl.halfFloat.HALF_FLOAT_OES, null);
|
||
|
default:
|
||
|
for (i in 0...6)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null);
|
||
|
}
|
||
|
|
||
|
if (format == DEPTH16) {
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
|
||
|
isDepthAttachment = true;
|
||
|
// Some WebGL implementations throw incomplete framebuffer error, create color attachment
|
||
|
if (!SystemImpl.gl2) {
|
||
|
var colortex = SystemImpl.gl.createTexture();
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, colortex);
|
||
|
for (i in 0...6) {
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL.RGBA, myWidth, myHeight, 0, GL.RGBA, GL.UNSIGNED_BYTE, null);
|
||
|
SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_CUBE_MAP_POSITIVE_X + i, colortex, 0);
|
||
|
}
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
initDepthStencilBuffer(depthStencilFormat);
|
||
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null);
|
||
|
}
|
||
|
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, null);
|
||
|
}
|
||
|
|
||
|
function initDepthStencilBuffer(depthStencilFormat: DepthStencilFormat) {
|
||
|
switch (depthStencilFormat) {
|
||
|
case NoDepthAndStencil:
|
||
|
case DepthOnly, Depth16:
|
||
|
{
|
||
|
depthTexture = SystemImpl.gl.createTexture();
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture);
|
||
|
if (depthStencilFormat == DepthOnly)
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL_DEPTH_COMPONENT24 : GL.DEPTH_COMPONENT, myWidth, myHeight, 0,
|
||
|
GL.DEPTH_COMPONENT, GL.UNSIGNED_INT, null);
|
||
|
else
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL.DEPTH_COMPONENT16 : GL.DEPTH_COMPONENT, myWidth, myHeight, 0,
|
||
|
GL.DEPTH_COMPONENT, GL.UNSIGNED_SHORT, null);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
|
||
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer);
|
||
|
SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_CUBE_MAP, depthTexture, 0);
|
||
|
}
|
||
|
case DepthAutoStencilAuto, Depth24Stencil8, Depth32Stencil8:
|
||
|
depthTexture = SystemImpl.gl.createTexture();
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture);
|
||
|
SystemImpl.gl.texImage2D(GL.TEXTURE_CUBE_MAP, 0, SystemImpl.gl2 ? GL_DEPTH24_STENCIL8 : GL.DEPTH_STENCIL, myWidth, myHeight, 0,
|
||
|
GL.DEPTH_STENCIL, SystemImpl.depthTexture.UNSIGNED_INT_24_8_WEBGL, null);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
|
||
|
SystemImpl.gl.texParameteri(GL.TEXTURE_CUBE_MAP, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
|
||
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, frameBuffer);
|
||
|
SystemImpl.gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_STENCIL_ATTACHMENT, GL.TEXTURE_CUBE_MAP, depthTexture, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function set(stage: Int): Void {
|
||
|
SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage);
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, texture);
|
||
|
}
|
||
|
|
||
|
public function setDepth(stage: Int): Void {
|
||
|
SystemImpl.gl.activeTexture(GL.TEXTURE0 + stage);
|
||
|
SystemImpl.gl.bindTexture(GL.TEXTURE_CUBE_MAP, depthTexture);
|
||
|
}
|
||
|
|
||
|
public function unload(): Void {}
|
||
|
|
||
|
public function lock(level: Int = 0): Bytes {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public function unlock(): Void {}
|
||
|
|
||
|
public var width(get, never): Int;
|
||
|
|
||
|
function get_width(): Int {
|
||
|
return myWidth;
|
||
|
}
|
||
|
|
||
|
public var height(get, never): Int;
|
||
|
|
||
|
function get_height(): Int {
|
||
|
return myHeight;
|
||
|
}
|
||
|
|
||
|
public var g1(get, never): kha.graphics1.Graphics;
|
||
|
|
||
|
function get_g1(): kha.graphics1.Graphics {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public var g2(get, never): kha.graphics2.Graphics;
|
||
|
|
||
|
function get_g2(): kha.graphics2.Graphics {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public var g4(get, never): kha.graphics4.Graphics;
|
||
|
|
||
|
function get_g4(): kha.graphics4.Graphics {
|
||
|
if (graphics4 == null) {
|
||
|
graphics4 = new Graphics(this);
|
||
|
}
|
||
|
return graphics4;
|
||
|
}
|
||
|
}
|