200 lines
7.7 KiB
Haxe
Raw Normal View History

2025-01-22 16:18:30 +01:00
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;
}
}