mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-11 19:48:54 +01:00
(Fixed) webgl
This commit is contained in:
parent
fc3a6ed373
commit
55f1a5d32e
@ -102,6 +102,7 @@ type context struct {
|
|||||||
|
|
||||||
locationCache *locationCache
|
locationCache *locationCache
|
||||||
screenFramebuffer framebufferNative // This might not be the default frame buffer '0' (e.g. iOS).
|
screenFramebuffer framebufferNative // This might not be the default frame buffer '0' (e.g. iOS).
|
||||||
|
mrtFramebuffer framebufferNative // The dynamic framebuffer used for MRT operations
|
||||||
lastFramebuffer framebufferNative
|
lastFramebuffer framebufferNative
|
||||||
lastTexture textureNative
|
lastTexture textureNative
|
||||||
lastRenderbuffer renderbufferNative
|
lastRenderbuffer renderbufferNative
|
||||||
@ -110,8 +111,6 @@ type context struct {
|
|||||||
lastBlend graphicsdriver.Blend
|
lastBlend graphicsdriver.Blend
|
||||||
maxTextureSize int
|
maxTextureSize int
|
||||||
maxTextureSizeOnce sync.Once
|
maxTextureSizeOnce sync.Once
|
||||||
highp bool
|
|
||||||
highpOnce sync.Once
|
|
||||||
initOnce sync.Once
|
initOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,26 +138,25 @@ func (c *context) bindFramebuffer(f framebufferNative) {
|
|||||||
c.lastFramebuffer = f
|
c.lastFramebuffer = f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) setViewport(f *framebuffer) {
|
func (c *context) setViewport(width, height int, screen bool) {
|
||||||
c.bindFramebuffer(f.native)
|
if c.lastViewportWidth == width && c.lastViewportHeight == height {
|
||||||
if c.lastViewportWidth == f.width && c.lastViewportHeight == f.height {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// On some environments, viewport size must be within the framebuffer size.
|
// On some environments, viewport size must be within the framebuffer size.
|
||||||
// e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691).
|
// e.g. Edge (#71), Chrome on GPD Pocket (#420), macOS Mojave (#691).
|
||||||
// Use the same size of the framebuffer here.
|
// Use the same size of the framebuffer here.
|
||||||
c.ctx.Viewport(0, 0, int32(f.width), int32(f.height))
|
c.ctx.Viewport(0, 0, int32(width), int32(height))
|
||||||
|
|
||||||
// glViewport must be called at least at every frame on iOS.
|
// glViewport must be called at least at every frame on iOS.
|
||||||
// As the screen framebuffer is the last render target, next SetViewport should be
|
// As the screen framebuffer is the last render target, next SetViewport should be
|
||||||
// the first call at a frame.
|
// the first call at a frame.
|
||||||
if f.native == c.screenFramebuffer {
|
if screen {
|
||||||
c.lastViewportWidth = 0
|
c.lastViewportWidth = 0
|
||||||
c.lastViewportHeight = 0
|
c.lastViewportHeight = 0
|
||||||
} else {
|
} else {
|
||||||
c.lastViewportWidth = f.width
|
c.lastViewportWidth = width
|
||||||
c.lastViewportHeight = f.height
|
c.lastViewportHeight = height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,16 +262,6 @@ func (c *context) framebufferPixels(buf []byte, f *framebuffer, region image.Rec
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) framebufferPixelsToBuffer(f *framebuffer, buffer buffer, width, height int) {
|
|
||||||
c.ctx.Flush()
|
|
||||||
|
|
||||||
c.bindFramebuffer(f.native)
|
|
||||||
|
|
||||||
c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, uint32(buffer))
|
|
||||||
c.ctx.ReadPixels(nil, 0, 0, int32(width), int32(height), gl.RGBA, gl.UNSIGNED_BYTE)
|
|
||||||
c.ctx.BindBuffer(gl.PIXEL_PACK_BUFFER, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *context) deleteTexture(t textureNative) {
|
func (c *context) deleteTexture(t textureNative) {
|
||||||
if c.lastTexture == t {
|
if c.lastTexture == t {
|
||||||
c.lastTexture = 0
|
c.lastTexture = 0
|
||||||
@ -357,7 +345,7 @@ func (c *context) bindStencilBuffer(f framebufferNative, r renderbufferNative) e
|
|||||||
|
|
||||||
c.ctx.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, uint32(r))
|
c.ctx.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, uint32(r))
|
||||||
if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
|
if s := c.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
|
||||||
return errors.New(fmt.Sprintf("opengl: glFramebufferRenderbuffer failed: %d", s))
|
return fmt.Errorf("opengl: glFramebufferRenderbuffer failed: %d", s)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ const (
|
|||||||
MIN = 0x8007
|
MIN = 0x8007
|
||||||
NEAREST = 0x2600
|
NEAREST = 0x2600
|
||||||
NO_ERROR = 0
|
NO_ERROR = 0
|
||||||
|
NONE = 0
|
||||||
NOTEQUAL = 0x0205
|
NOTEQUAL = 0x0205
|
||||||
ONE = 1
|
ONE = 1
|
||||||
ONE_MINUS_DST_ALPHA = 0x0305
|
ONE_MINUS_DST_ALPHA = 0x0305
|
||||||
|
@ -54,6 +54,7 @@ type defaultContext struct {
|
|||||||
fnDeleteVertexArray js.Value
|
fnDeleteVertexArray js.Value
|
||||||
fnDisable js.Value
|
fnDisable js.Value
|
||||||
fnDisableVertexAttribArray js.Value
|
fnDisableVertexAttribArray js.Value
|
||||||
|
fnDrawBuffers js.Value
|
||||||
fnDrawElements js.Value
|
fnDrawElements js.Value
|
||||||
fnEnable js.Value
|
fnEnable js.Value
|
||||||
fnEnableVertexAttribArray js.Value
|
fnEnableVertexAttribArray js.Value
|
||||||
@ -184,6 +185,7 @@ func NewDefaultContext(v js.Value) (Context, error) {
|
|||||||
fnDeleteVertexArray: v.Get("deleteVertexArray").Call("bind", v),
|
fnDeleteVertexArray: v.Get("deleteVertexArray").Call("bind", v),
|
||||||
fnDisable: v.Get("disable").Call("bind", v),
|
fnDisable: v.Get("disable").Call("bind", v),
|
||||||
fnDisableVertexAttribArray: v.Get("disableVertexAttribArray").Call("bind", v),
|
fnDisableVertexAttribArray: v.Get("disableVertexAttribArray").Call("bind", v),
|
||||||
|
fnDrawBuffers: v.Get("drawBuffers").Call("bind", v),
|
||||||
fnDrawElements: v.Get("drawElements").Call("bind", v),
|
fnDrawElements: v.Get("drawElements").Call("bind", v),
|
||||||
fnEnable: v.Get("enable").Call("bind", v),
|
fnEnable: v.Get("enable").Call("bind", v),
|
||||||
fnEnableVertexAttribArray: v.Get("enableVertexAttribArray").Call("bind", v),
|
fnEnableVertexAttribArray: v.Get("enableVertexAttribArray").Call("bind", v),
|
||||||
@ -384,6 +386,11 @@ func (c *defaultContext) DisableVertexAttribArray(index uint32) {
|
|||||||
c.fnDisableVertexAttribArray.Invoke(index)
|
c.fnDisableVertexAttribArray.Invoke(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *defaultContext) DrawBuffers(bufs []uint32) {
|
||||||
|
arr := jsutil.NewUint32Array(bufs)
|
||||||
|
c.fnDrawBuffers.Invoke(arr)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
|
func (c *defaultContext) DrawElements(mode uint32, count int32, xtype uint32, offset int) {
|
||||||
c.fnDrawElements.Invoke(mode, count, xtype, offset)
|
c.fnDrawElements.Invoke(mode, count, xtype, offset)
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,8 @@ type Graphics struct {
|
|||||||
// drawCalled is true just after Draw is called. This holds true until WritePixels is called.
|
// drawCalled is true just after Draw is called. This holds true until WritePixels is called.
|
||||||
drawCalled bool
|
drawCalled bool
|
||||||
|
|
||||||
uniformVariableNameCache map[int]string
|
uniformVariableNameCache map[int]string
|
||||||
textureVariableNameCache map[int]string
|
textureVariableNameCache map[int]string
|
||||||
|
|
||||||
uniformVars []uniformVariable
|
uniformVars []uniformVariable
|
||||||
|
|
||||||
@ -204,9 +204,9 @@ func (g *Graphics) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdr
|
|||||||
}
|
}
|
||||||
|
|
||||||
g.drawCalled = true
|
g.drawCalled = true
|
||||||
|
g.context.ctx.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
dstCount := 0
|
dstCount := 0
|
||||||
var destinations [graphics.ShaderDstImageCount]*Image
|
var dsts [graphics.ShaderDstImageCount]*Image
|
||||||
for i, dstID := range dstIDs {
|
for i, dstID := range dstIDs {
|
||||||
if dstID == graphicsdriver.InvalidImageID {
|
if dstID == graphicsdriver.InvalidImageID {
|
||||||
continue
|
continue
|
||||||
@ -215,27 +215,66 @@ func (g *Graphics) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdr
|
|||||||
if dst == nil {
|
if dst == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
destinations[i] = dst
|
dst.ensureFramebuffer()
|
||||||
|
dsts[i] = dst
|
||||||
dstCount++
|
dstCount++
|
||||||
}
|
}
|
||||||
if dstCount == 0 {
|
if dstCount == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
g.context.bindFramebuffer(0)
|
||||||
|
|
||||||
// Only necessary for the same shared framebuffer
|
// Only necessary for the same shared framebuffer
|
||||||
if err := destinations[0].setViewport(); err != nil {
|
f := uint32(dsts[0].framebuffer.native)
|
||||||
return err
|
if dstCount > 1 {
|
||||||
|
if g.context.mrtFramebuffer == 0 {
|
||||||
|
f = g.context.ctx.CreateFramebuffer()
|
||||||
|
if f <= 0 {
|
||||||
|
return fmt.Errorf("opengl: creating framebuffer failed: the returned value is not positive but %d", f)
|
||||||
|
}
|
||||||
|
g.context.mrtFramebuffer = framebufferNative(f)
|
||||||
|
} else {
|
||||||
|
f = uint32(g.context.mrtFramebuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.context.bindFramebuffer(framebufferNative(f))
|
||||||
|
//g.context.ctx.BindFramebuffer(gl.FRAMEBUFFER, f)
|
||||||
|
|
||||||
|
// Reset color attachments
|
||||||
|
if s := g.context.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s == gl.FRAMEBUFFER_COMPLETE {
|
||||||
|
g.context.ctx.Clear(16384 | gl.STENCIL_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
for i, dst := range dsts {
|
||||||
|
if dst == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.context.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+uint32(i), gl.TEXTURE_2D, uint32(dst.texture), 0)
|
||||||
|
}
|
||||||
|
if s := g.context.ctx.CheckFramebufferStatus(gl.FRAMEBUFFER); s != gl.FRAMEBUFFER_COMPLETE {
|
||||||
|
if s != 0 {
|
||||||
|
return fmt.Errorf("opengl: creating framebuffer failed: %v", s)
|
||||||
|
}
|
||||||
|
if e := g.context.ctx.GetError(); e != gl.NO_ERROR {
|
||||||
|
return fmt.Errorf("opengl: creating framebuffer failed: (glGetError) %d", e)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("opengl: creating framebuffer failed: unknown error")
|
||||||
|
}
|
||||||
|
// Color attachments
|
||||||
|
var attached []uint32
|
||||||
|
for i, dst := range dsts {
|
||||||
|
if dst == nil {
|
||||||
|
attached = append(attached, gl.NONE)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
attached = append(attached, uint32(gl.COLOR_ATTACHMENT0+i))
|
||||||
|
}
|
||||||
|
g.context.ctx.DrawBuffers(attached)
|
||||||
|
} else {
|
||||||
|
g.context.bindFramebuffer(framebufferNative(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color attachments
|
w, h := dsts[0].framebufferSize()
|
||||||
var attached []uint32
|
g.context.setViewport(w, h, dsts[0].screen)
|
||||||
for i, dst := range destinations {
|
|
||||||
if dst == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
attached = append(attached, uint32(gl.COLOR_ATTACHMENT0+i))
|
|
||||||
g.context.ctx.FramebufferTexture2D(gl.FRAMEBUFFER, uint32(gl.COLOR_ATTACHMENT0+i), gl.TEXTURE_2D, uint32(dst.texture), 0)
|
|
||||||
}
|
|
||||||
g.context.ctx.DrawBuffers(attached)
|
|
||||||
|
|
||||||
g.context.blend(blend)
|
g.context.blend(blend)
|
||||||
|
|
||||||
@ -259,7 +298,7 @@ func (g *Graphics) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In OpenGL, the NDC's Y direction is upward, so flip the Y direction for the final framebuffer.
|
// In OpenGL, the NDC's Y direction is upward, so flip the Y direction for the final framebuffer.
|
||||||
if dstCount == 1 && destinations[0] != nil && destinations[0].screen {
|
if dstCount == 1 && dsts[0] != nil && dsts[0].screen {
|
||||||
const idx = graphics.ProjectionMatrixUniformVariableIndex
|
const idx = graphics.ProjectionMatrixUniformVariableIndex
|
||||||
// Invert the sign bits as float32 values.
|
// Invert the sign bits as float32 values.
|
||||||
g.uniformVars[idx].value[1] ^= 1 << 31
|
g.uniformVars[idx].value[1] ^= 1 << 31
|
||||||
@ -287,11 +326,11 @@ func (g *Graphics) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdr
|
|||||||
g.uniformVars = g.uniformVars[:0]
|
g.uniformVars = g.uniformVars[:0]
|
||||||
|
|
||||||
if fillRule != graphicsdriver.FillAll {
|
if fillRule != graphicsdriver.FillAll {
|
||||||
for _, dst := range destinations {
|
for _, dst := range dsts {
|
||||||
if dst == nil {
|
if dst == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := dst.ensureStencilBuffer(); err != nil {
|
if err := dst.ensureStencilBuffer(framebufferNative(f)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -336,6 +375,10 @@ func (g *Graphics) DrawTriangles(dstIDs [graphics.ShaderDstImageCount]graphicsdr
|
|||||||
g.context.ctx.Disable(gl.STENCIL_TEST)
|
g.context.ctx.Disable(gl.STENCIL_TEST)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detach existing color attachments
|
||||||
|
//g.context.bindFramebuffer(fb)
|
||||||
|
//TODO:
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ type Image struct {
|
|||||||
|
|
||||||
// framebuffer is a wrapper of OpenGL's framebuffer.
|
// framebuffer is a wrapper of OpenGL's framebuffer.
|
||||||
type framebuffer struct {
|
type framebuffer struct {
|
||||||
graphics *Graphics
|
|
||||||
native framebufferNative
|
native framebufferNative
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
@ -61,14 +60,6 @@ func (i *Image) Dispose() {
|
|||||||
i.graphics.removeImage(i)
|
i.graphics.removeImage(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) setViewport() error {
|
|
||||||
if err := i.ensureFramebuffer(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
i.graphics.context.setViewport(i.framebuffer)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Image) ReadPixels(args []graphicsdriver.PixelsArgs) error {
|
func (i *Image) ReadPixels(args []graphicsdriver.PixelsArgs) error {
|
||||||
if err := i.ensureFramebuffer(); err != nil {
|
if err := i.ensureFramebuffer(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -109,14 +100,14 @@ func (i *Image) ensureFramebuffer() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ensureStencilBuffer() error {
|
func (i *Image) ensureStencilBuffer(f framebufferNative) error {
|
||||||
if i.stencil != 0 {
|
if i.stencil != 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := i.ensureFramebuffer(); err != nil {
|
/*if err := i.ensureFramebuffer(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}*/
|
||||||
|
|
||||||
r, err := i.graphics.context.newRenderbuffer(i.framebufferSize())
|
r, err := i.graphics.context.newRenderbuffer(i.framebufferSize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -124,7 +115,7 @@ func (i *Image) ensureStencilBuffer() error {
|
|||||||
}
|
}
|
||||||
i.stencil = r
|
i.stencil = r
|
||||||
|
|
||||||
if err := i.graphics.context.bindStencilBuffer(i.framebuffer.native, i.stencil); err != nil {
|
if err := i.graphics.context.bindStencilBuffer(f, i.stencil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -24,6 +24,7 @@ var (
|
|||||||
uint8Array = js.Global().Get("Uint8Array")
|
uint8Array = js.Global().Get("Uint8Array")
|
||||||
float32Array = js.Global().Get("Float32Array")
|
float32Array = js.Global().Get("Float32Array")
|
||||||
int32Array = js.Global().Get("Int32Array")
|
int32Array = js.Global().Get("Int32Array")
|
||||||
|
uint32Array = js.Global().Get("Uint32Array")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -40,8 +41,11 @@ var (
|
|||||||
// temporaryFloat32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
// temporaryFloat32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
||||||
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
||||||
|
|
||||||
// temporaryInt32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
// temporaryInt32Array is a Int32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
||||||
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
||||||
|
|
||||||
|
// temporaryUint32Array is a Uint32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
||||||
|
temporaryUint32Array = uint32Array.New(temporaryArrayBuffer)
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureTemporaryArrayBufferSize(byteLength int) {
|
func ensureTemporaryArrayBufferSize(byteLength int) {
|
||||||
@ -54,6 +58,7 @@ func ensureTemporaryArrayBufferSize(byteLength int) {
|
|||||||
temporaryUint8Array = uint8Array.New(temporaryArrayBuffer)
|
temporaryUint8Array = uint8Array.New(temporaryArrayBuffer)
|
||||||
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
||||||
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
||||||
|
temporaryUint32Array = uint32Array.New(temporaryArrayBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,3 +106,11 @@ func TemporaryInt32Array(minLength int, data []int32) js.Value {
|
|||||||
copySliceToTemporaryArrayBuffer(data)
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
return temporaryInt32Array
|
return temporaryInt32Array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewUint32Array returns a Uint32Array whose length is equal to the length of data.
|
||||||
|
func NewUint32Array(data []uint32) js.Value {
|
||||||
|
ensureTemporaryArrayBufferSize(len(data) * 4)
|
||||||
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
|
a := temporaryUint32Array.Call("slice", 0, len(data))
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
@ -229,6 +229,12 @@ func Compile(p *shaderir.Program, version GLSLVersion) (vertexShader, fragmentSh
|
|||||||
fslines = append(fslines, fmt.Sprintf("in %s;", c.varDecl(p, &t, fmt.Sprintf("V%d", i))))
|
fslines = append(fslines, fmt.Sprintf("in %s;", c.varDecl(p, &t, fmt.Sprintf("V%d", i))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If ES300 out colors need to be defined explicitely
|
||||||
|
if version == GLSLVersionES300 {
|
||||||
|
for i := 0; i < p.ColorsOutCount; i++ {
|
||||||
|
fslines = append(fslines, fmt.Sprintf("layout(location = %d) out vec4 glFragColor%d;", i, i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var funcs []*shaderir.Func
|
var funcs []*shaderir.Func
|
||||||
if p.VertexFunc.Block != nil {
|
if p.VertexFunc.Block != nil {
|
||||||
@ -420,6 +426,9 @@ func (c *compileContext) localVariableName(p *shaderir.Program, topBlock *shader
|
|||||||
case idx < nv+1:
|
case idx < nv+1:
|
||||||
return fmt.Sprintf("V%d", idx-1)
|
return fmt.Sprintf("V%d", idx-1)
|
||||||
default:
|
default:
|
||||||
|
if c.version == GLSLVersionES300 {
|
||||||
|
return fmt.Sprintf("glFragColor%d", idx-(nv+1))
|
||||||
|
}
|
||||||
return fmt.Sprintf("gl_FragData[%d]", idx-(nv+1))
|
return fmt.Sprintf("gl_FragData[%d]", idx-(nv+1))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user