driver: Add (Graphics).HasHighPrecisionFlaot

This enables to determine whether vertices should be adjusted or
not.

Fixes #879
This commit is contained in:
Hajime Hoshi 2019-06-22 04:47:48 +09:00
parent cddb93b9f6
commit 9bff33472a
8 changed files with 49 additions and 7 deletions

View File

@ -35,6 +35,7 @@ type Graphics interface {
VDirection() VDirection VDirection() VDirection
NeedsRestoring() bool NeedsRestoring() bool
IsGL() bool IsGL() bool
HasHighPrecisionFloat() bool
} }
type Image interface { type Image interface {

View File

@ -183,14 +183,15 @@ func (q *commandQueue) Flush() {
fmt.Println("--") fmt.Println("--")
} }
if theGraphicsDriver.HasHighPrecisionFloat() {
// Adjust texels. // Adjust texels.
// TODO: texelAdjustmentFactor can vary depends on the highp precisions (#879).
const texelAdjustmentFactor = 1.0 / 512.0 const texelAdjustmentFactor = 1.0 / 512.0
for i := 0; i < q.nvertices/graphics.VertexFloatNum; i++ { for i := 0; i < q.nvertices/graphics.VertexFloatNum; i++ {
s := q.dstSizes[i] s := q.dstSizes[i]
vs[i*graphics.VertexFloatNum+6] -= 1.0 / s.width * texelAdjustmentFactor vs[i*graphics.VertexFloatNum+6] -= 1.0 / s.width * texelAdjustmentFactor
vs[i*graphics.VertexFloatNum+7] -= 1.0 / s.height * texelAdjustmentFactor vs[i*graphics.VertexFloatNum+7] -= 1.0 / s.height * texelAdjustmentFactor
} }
}
theGraphicsDriver.Begin() theGraphicsDriver.Begin()
for len(q.commands) > 0 { for len(q.commands) > 0 {

View File

@ -703,6 +703,10 @@ func (d *Driver) IsGL() bool {
return false return false
} }
func (d *Driver) HasHighPrecisionFloat() bool {
return true
}
type Image struct { type Image struct {
driver *Driver driver *Driver
width int width int

View File

@ -16,6 +16,7 @@ package opengl
import ( import (
"fmt" "fmt"
"sync"
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/thread" "github.com/hajimehoshi/ebiten/internal/thread"
@ -49,6 +50,8 @@ type context struct {
lastViewportHeight int lastViewportHeight int
lastCompositeMode graphics.CompositeMode lastCompositeMode graphics.CompositeMode
maxTextureSize int maxTextureSize int
highp bool
highpOnce sync.Once
t *thread.Thread t *thread.Thread
@ -102,3 +105,13 @@ func (c *context) getMaxTextureSize() int {
} }
return c.maxTextureSize return c.maxTextureSize
} }
// highpPrecision represents an enough mantissa of float values in a shader.
const highpPrecision = 23
func (c *context) hasHighPrecisionFloat() bool {
c.highpOnce.Do(func() {
c.highp = c.getShaderPrecisionFormatPrecision() >= highpPrecision
})
return c.highp
}

View File

@ -493,6 +493,12 @@ func (c *context) maxTextureSizeImpl() int {
return size return size
} }
func (c *context) getShaderPrecisionFormatPrecision() int {
// glGetShaderPrecisionFormat is not defined at OpenGL 2.0. Assume that desktop environments always have
// enough highp precision.
return highpPrecision
}
func (c *context) flush() { func (c *context) flush() {
_ = c.t.Call(func() error { _ = c.t.Call(func() error {
gl.Flush() gl.Flush()

View File

@ -73,6 +73,7 @@ var (
framebuffer_ = contextPrototype.Get("FRAMEBUFFER") framebuffer_ = contextPrototype.Get("FRAMEBUFFER")
framebufferBinding = contextPrototype.Get("FRAMEBUFFER_BINDING") framebufferBinding = contextPrototype.Get("FRAMEBUFFER_BINDING")
framebufferComplete = contextPrototype.Get("FRAMEBUFFER_COMPLETE") framebufferComplete = contextPrototype.Get("FRAMEBUFFER_COMPLETE")
highFloat = contextPrototype.Get("HIGH_FLOAT")
linkStatus = contextPrototype.Get("LINK_STATUS") linkStatus = contextPrototype.Get("LINK_STATUS")
maxTextureSize = contextPrototype.Get("MAX_TEXTURE_SIZE") maxTextureSize = contextPrototype.Get("MAX_TEXTURE_SIZE")
nearest = contextPrototype.Get("NEAREST") nearest = contextPrototype.Get("NEAREST")
@ -451,6 +452,12 @@ func (c *context) maxTextureSizeImpl() int {
return gl.Call("getParameter", maxTextureSize).Int() return gl.Call("getParameter", maxTextureSize).Int()
} }
func (c *context) getShaderPrecisionFormatPrecision() int {
c.ensureGL()
gl := c.gl
return gl.Call("getShaderPrecisionFormat", js.ValueOf(int(fragmentShader)), highFloat).Get("precision").Int()
}
func (c *context) flush() { func (c *context) flush() {
c.ensureGL() c.ensureGL()
gl := c.gl gl := c.gl

View File

@ -377,6 +377,12 @@ func (c *context) maxTextureSizeImpl() int {
return gl.GetInteger(mgl.MAX_TEXTURE_SIZE) return gl.GetInteger(mgl.MAX_TEXTURE_SIZE)
} }
func (c *context) getShaderPrecisionFormatPrecision() int {
gl := c.gl
_, _, p := gl.GetShaderPrecisionFormat(mgl.FRAGMENT_SHADER, mgl.HIGH_FLOAT)
return p
}
func (c *context) flush() { func (c *context) flush() {
gl := c.gl gl := c.gl
gl.Flush() gl.Flush()

View File

@ -138,3 +138,7 @@ func (d *Driver) NeedsRestoring() bool {
func (d *Driver) IsGL() bool { func (d *Driver) IsGL() bool {
return true return true
} }
func (d *Driver) HasHighPrecisionFloat() bool {
return d.context.hasHighPrecisionFloat()
}