Skip to content

Commit 38f5a77

Browse files
committed
crt preferences window shows scaled image of CRT
added mask/scanlines scaling option default noise level reduced reduced noise level range in preferences window
1 parent 2fd42f5 commit 38f5a77

File tree

8 files changed

+119
-24
lines changed

8 files changed

+119
-24
lines changed

gui/crt/preferences.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Preferences struct {
3333
MaskBrightness prefs.Float
3434
ScanlinesBrightness prefs.Float
3535
NoiseLevel prefs.Float
36+
MaskScanlineScaling prefs.Int
3637

3738
Vignette prefs.Bool
3839
}
@@ -49,8 +50,10 @@ const (
4950
noise = true
5051
maskBrightness = 0.70
5152
scanlinesBrightness = 0.70
52-
noiseLevel = 0.15
53-
vignette = true
53+
noiseLevel = 0.10
54+
maskScanlineScaling = 1
55+
56+
vignette = true
5457
)
5558

5659
// NewPreferences is the preferred method of initialisation for the Preferences type.
@@ -97,11 +100,14 @@ func NewPreferences() (*Preferences, error) {
97100
if err != nil {
98101
return nil, err
99102
}
103+
err = p.dsk.Add("crt.maskScanlineScaling", &p.MaskScanlineScaling)
104+
if err != nil {
105+
return nil, err
106+
}
100107
err = p.dsk.Add("crt.noiseLevel", &p.NoiseLevel)
101108
if err != nil {
102109
return nil, err
103110
}
104-
105111
err = p.dsk.Add("crt.vignette", &p.Vignette)
106112
if err != nil {
107113
return nil, err
@@ -124,6 +130,7 @@ func (p *Preferences) SetDefaults() {
124130
p.Noise.Set(noise)
125131
p.MaskBrightness.Set(maskBrightness)
126132
p.ScanlinesBrightness.Set(scanlinesBrightness)
133+
p.MaskScanlineScaling.Set(maskScanlineScaling)
127134
p.NoiseLevel.Set(noiseLevel)
128135
p.Vignette.Set(vignette)
129136
}

gui/crt/shaders/generator/fragment.glsl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ uniform float MaskBrightness;
2323
uniform float ScanlinesBrightness;
2424
uniform float NoiseLevel;
2525
uniform int Vignette;
26+
uniform int MaskScanlineScaling;
2627

2728
uniform sampler2D Texture;
2829
in vec2 Frag_UV;
@@ -216,7 +217,7 @@ void main()
216217
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
217218

218219
// if pixel-perfect rendering is selected then there's nothing much more to do
219-
if (CRT == 0) {
220+
if (CRT == 0 && ImageType != 4) {
220221
return;
221222
}
222223

@@ -233,6 +234,8 @@ void main()
233234
//
234235
// https://github.com/libretro/glsl-shaders/blob/master/crt/shaders/crt-pi.glsl
235236

237+
int scaling = MaskScanlineScaling + 1;
238+
236239
// noise
237240
if (Noise == 1) {
238241
float r;
@@ -244,7 +247,6 @@ void main()
244247
} else {
245248
Out_Color.b *= max(1.0-NoiseLevel, gold_noise(gl_FragCoord.xy));
246249
}
247-
248250
}
249251

250252
// input gamma
@@ -253,7 +255,11 @@ void main()
253255
// masking
254256
if (Mask == 1) {
255257
vec3 mask;
256-
if (fract(gl_FragCoord.x * 0.5) < 0.5) {
258+
259+
/* if (fract(gl_FragCoord.x * 0.5) < 0.5) { */
260+
261+
float oneCol = gl_FragCoord.x/gl_FragCoord.x;
262+
if ( isNearEqual(mod(gl_FragCoord.x, scaling*oneCol), 0.0, oneCol) ) {
257263
mask = vec3(MaskBrightness, 1.0, MaskBrightness);
258264
} else {
259265
mask = vec3(1.0, MaskBrightness, 1.0);
@@ -263,7 +269,10 @@ void main()
263269

264270
// scanline effect
265271
if (Scanlines == 1) {
266-
if (fract(gl_FragCoord.y * 0.5) < 0.5) {
272+
/* if (fract(gl_FragCoord.y * 0.5) < 0.5) { */
273+
274+
float oneLine = gl_FragCoord.y/gl_FragCoord.y;
275+
if ( isNearEqual(mod(gl_FragCoord.y, scaling*oneLine), 0.0, oneLine) ) {
267276
Out_Color.a = Out_Color.a * ScanlinesBrightness;
268277
}
269278
}

gui/crt/shaders/shaders.go

Lines changed: 13 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gui/sdlimgui/glsl.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ type glsl struct {
8383
attribScanlinesBrightness int32 // uniform
8484
attribNoiseLevel int32 // uniform
8585
attribVignette int32 // uniform
86+
attribMaskScanlineScaling int32 // uniform
8687
}
8788

8889
func newGlsl(io imgui.IO, img *SdlImgui) (*glsl, error) {
@@ -230,6 +231,7 @@ func (rnd *glsl) render(displaySize [2]float32, framebufferSize [2]float32, draw
230231
gl.Uniform1f(rnd.attribScanlinesBrightness, float32(rnd.img.crtPrefs.ScanlinesBrightness.Get().(float64)))
231232
gl.Uniform1f(rnd.attribNoiseLevel, float32(rnd.img.crtPrefs.NoiseLevel.Get().(float64)))
232233
gl.Uniform1i(rnd.attribVignette, boolToInt32(rnd.img.crtPrefs.Vignette.Get().(bool)))
234+
gl.Uniform1i(rnd.attribMaskScanlineScaling, int32(rnd.img.crtPrefs.MaskScanlineScaling.Get().(int)))
233235

234236
// critical section
235237
rnd.img.screen.crit.section.Lock()
@@ -309,6 +311,8 @@ func (rnd *glsl) render(displaySize [2]float32, framebufferSize [2]float32, draw
309311
gl.Uniform1i(rnd.attribImageType, 2)
310312
case rnd.img.wm.playScr.screenTexture:
311313
gl.Uniform1i(rnd.attribImageType, 3)
314+
case rnd.img.wm.crtPrefs.crtTexture:
315+
gl.Uniform1i(rnd.attribImageType, 4)
312316
default:
313317
gl.Uniform1i(rnd.attribImageType, 0)
314318
}
@@ -400,6 +404,7 @@ func (rnd *glsl) setup() {
400404
rnd.attribScanlinesBrightness = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("ScanlinesBrightness"+"\x00"))
401405
rnd.attribNoiseLevel = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("NoiseLevel"+"\x00"))
402406
rnd.attribVignette = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("Vignette"+"\x00"))
407+
rnd.attribMaskScanlineScaling = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("MaskScanlineScaling"+"\x00"))
403408

404409
rnd.attribTexture = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("Texture"+"\x00"))
405410
rnd.attribProjMtx = gl.GetUniformLocation(rnd.shaderHandle, gl.Str("ProjMtx"+"\x00"))

gui/sdlimgui/screen.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,10 @@ func (scr *screen) resize(spec specification.Spec, topScanline int, visibleScanl
149149
}
150150

151151
// create a cropped image from the main
152-
r := image.Rectangle{
153-
image.Point{specification.HorizClksHBlank,
154-
scr.crit.topScanline,
155-
},
156-
image.Point{specification.HorizClksHBlank + specification.HorizClksVisible,
157-
scr.crit.topScanline + scr.crit.scanlines,
158-
},
159-
}
152+
r := image.Rect(
153+
specification.HorizClksHBlank, scr.crit.topScanline,
154+
specification.HorizClksHBlank+specification.HorizClksVisible, scr.crit.topScanline+scr.crit.scanlines,
155+
)
160156
scr.crit.cropPixels = scr.crit.pixels.SubImage(r).(*image.RGBA)
161157
scr.crit.cropElementPixels = scr.crit.elementPixels.SubImage(r).(*image.RGBA)
162158
scr.crit.cropOverlayPixels = scr.crit.overlayPixels.SubImage(r).(*image.RGBA)
Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,38 @@ package sdlimgui
1717

1818
import (
1919
"fmt"
20+
"image"
2021

22+
"github.com/go-gl/gl/v3.2-core/gl"
2123
"github.com/inkyblackness/imgui-go/v2"
24+
"github.com/jetsetilly/gopher2600/hardware/television/specification"
2225
"github.com/jetsetilly/gopher2600/logger"
2326
)
2427

2528
const winCRTPrefsTitle = "CRT Preferences"
2629

2730
type winCRTPrefs struct {
2831
windowManagement
32+
2933
img *SdlImgui
34+
scr *screen
35+
36+
crtTexture uint32
37+
pixels *image.RGBA
3038
}
3139

3240
func newWinCRTPrefs(img *SdlImgui) (managedWindow, error) {
3341
win := &winCRTPrefs{
3442
img: img,
43+
scr: img.screen,
3544
}
3645

46+
gl.ActiveTexture(gl.TEXTURE0)
47+
gl.GenTextures(1, &win.crtTexture)
48+
gl.BindTexture(gl.TEXTURE_2D, win.crtTexture)
49+
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
50+
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
51+
3752
return win, nil
3853
}
3954

@@ -47,14 +62,43 @@ func (win *winCRTPrefs) id() string {
4762
return winCRTPrefsTitle
4863
}
4964

65+
// height/width for detailPixels.
66+
const (
67+
detailPixelsWidth = 50
68+
detailPixelsHeight = 100
69+
)
70+
71+
// the amount to adjust the pixel view to account for the HMOVE margin.
72+
const HmoveMargin = 16
73+
5074
func (win *winCRTPrefs) draw() {
5175
if !win.open {
5276
return
5377
}
5478

79+
win.scr.crit.section.Lock()
80+
81+
r := image.Rect(
82+
specification.HorizClksHBlank+HmoveMargin, win.scr.crit.topScanline,
83+
specification.HorizClksHBlank+HmoveMargin+detailPixelsWidth, win.scr.crit.topScanline+detailPixelsHeight,
84+
)
85+
win.pixels = win.scr.crit.pixels.SubImage(r).(*image.RGBA)
86+
87+
gl.PixelStorei(gl.UNPACK_ROW_LENGTH, int32(win.pixels.Stride)/4)
88+
gl.BindTexture(gl.TEXTURE_2D, win.crtTexture)
89+
gl.TexImage2D(gl.TEXTURE_2D, 0,
90+
gl.RGBA, detailPixelsWidth, detailPixelsHeight, 0,
91+
gl.RGBA, gl.UNSIGNED_BYTE,
92+
gl.Ptr(win.pixels.Pix))
93+
94+
gl.PixelStorei(gl.UNPACK_ROW_LENGTH, 0)
95+
win.scr.crit.section.Unlock()
96+
5597
imgui.SetNextWindowPosV(imgui.Vec2{10, 10}, imgui.ConditionFirstUseEver, imgui.Vec2{0, 0})
5698
imgui.BeginV(winCRTPrefsTitle, &win.open, imgui.WindowFlagsAlwaysAutoResize)
5799

100+
imgui.BeginGroup()
101+
58102
win.drawGamma()
59103

60104
imgui.Spacing()
@@ -79,6 +123,18 @@ func (win *winCRTPrefs) draw() {
79123
if imgui.Checkbox("Vignette##vignette", &b) {
80124
win.img.crtPrefs.Vignette.Set(b)
81125
}
126+
imgui.Spacing()
127+
imgui.Spacing()
128+
129+
win.drawMaskScanlineScaling()
130+
131+
imgui.EndGroup()
132+
133+
imgui.SameLine()
134+
135+
imgui.BeginGroup()
136+
imgui.Image(imgui.TextureID(win.crtTexture), imgui.Vec2{300, 300})
137+
imgui.EndGroup()
82138

83139
imgui.Spacing()
84140
imgui.Separator()
@@ -123,13 +179,20 @@ func (win *winCRTPrefs) drawScanlines() {
123179
}
124180
}
125181

182+
func (win *winCRTPrefs) drawMaskScanlineScaling() {
183+
f := int32(win.img.crtPrefs.MaskScanlineScaling.Get().(int))
184+
if imgui.SliderIntV("Mask/Scanline Scaling##scaling", &f, 1, 3, "%d") {
185+
win.img.crtPrefs.MaskScanlineScaling.Set(f)
186+
}
187+
}
188+
126189
func (win *winCRTPrefs) drawNoise() {
127190
b := win.img.crtPrefs.Noise.Get().(bool)
128191
if imgui.Checkbox("Noise##noise", &b) {
129192
win.img.crtPrefs.Noise.Set(b)
130193
}
131194
f := float32(win.img.crtPrefs.NoiseLevel.Get().(float64))
132-
if imgui.SliderFloatV("Level##noiselevel", &f, 0.0, 1.0, "%.2f", 1.0) {
195+
if imgui.SliderFloatV("Level##noiselevel", &f, 0.0, 0.2, "%.2f", 1.0) {
133196
win.img.crtPrefs.NoiseLevel.Set(f)
134197
}
135198
}

gui/sdlimgui/windowmanager.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ type windowManager struct {
6868
windowMenu map[string][]string
6969

7070
// some windows need to be referenced elsewhere
71-
term *winTerm
72-
dbgScr *winDbgScr
73-
playScr *winPlayScr
74-
disasm *winDisasm
71+
term *winTerm
72+
dbgScr *winDbgScr
73+
playScr *winPlayScr
74+
disasm *winDisasm
75+
crtPrefs *winCRTPrefs
7576

7677
// the position of the screen on the current display. the SDL function
7778
// Window.GetPosition() is unsuitable for use in conjunction with imgui
@@ -220,6 +221,7 @@ func newWindowManager(img *SdlImgui) (*windowManager, error) {
220221
wm.dbgScr = wm.windows[winDbgScrTitle].(*winDbgScr)
221222
wm.term = wm.windows[winTermTitle].(*winTerm)
222223
wm.disasm = wm.windows[winDisasmTitle].(*winDisasm)
224+
wm.crtPrefs = wm.windows[winCRTPrefsTitle].(*winCRTPrefs)
223225

224226
// create play window. this is a very special window that never appears
225227
// directly in an any menu

prefs/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ func (p *Int) Set(v Value) error {
222222
// new value
223223
var nv int
224224
switch v := v.(type) {
225+
case int64:
226+
nv = int(v)
227+
case int32:
228+
nv = int(v)
225229
case int:
226230
nv = v
227231
case string:

0 commit comments

Comments
 (0)