Skip to content

Commit

Permalink
Add 'NDS Color' + 'Natural Vision' variants of all shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
jdgleaver committed Apr 28, 2022
1 parent 2b28fb3 commit 4b477eb
Show file tree
Hide file tree
Showing 7 changed files with 532 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Some shaders for [DraStic DS](https://play.google.com/store/apps/details?id=com.

- All shaders include a '+ Natural Vision' variant, which applies ShadX's 'Natural Vision' colour (saturation) enhancement

- All shaders include a '+ NDS Color + Natural Vision' variant, which applies DS Phat colour correction followed by ShadX's 'Natural Vision' colour enhancement

- All shaders work correctly with 'High-Resolution 3D Rendering' turned ON or OFF

- All shaders run at full speed on mid-to-low-range Android devices
Expand Down
44 changes: 44 additions & 0 deletions lcd1x+nds_color+natural_vision.dfx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// lcd1x+nds_color+natural_vision shader
=============================================
<options>
name=LCD1x + NDS Color + Natural Vision
textures=1
</options>

<fheader>
#if GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
// Configuration
#define BRIGHTEN_SCANLINES 16.0 // "Brighten Scanlines"
// - default: 16.0, min: 1.0, max: 32.0, step: 0.5
// (brightness of horizontal lines)
#define BRIGHTEN_LCD 4.0 // "Brighten LCD"
// - default: 4.0, min: 1.0, max: 12.0, step: 0.1
// (brightness of vertical lines)
#define NATVIS_GIN 1.91 // "NaturalVision Gamma In"
// - default: 1.91, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_GOUT 1.91 // "NaturalVision Gamma Out"
// - default: 1.91, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_Y 1.1 // "NaturalVision Luminance"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_I 1.1 // "NaturalVision Orange-Cyan"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_Q 1.1 // "NaturalVision Magenta-Green"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
</fheader>

<texture:0>
input=framebuffer
min_filter=GL_NEAREST
mag_filter=GL_NEAREST
</texture>

<pass>
shader=lcd1x+nds_color+natural_vision.dsd
sampler:u_texture=0
</pass>
140 changes: 140 additions & 0 deletions lcd1x+nds_color+natural_vision.dsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// lcd1x+nds_color+natural_vision - Simple LCD 'scanline' shader, based on lcd3x
//
// - Original lcd3x code by Gigaherz, released into the public domain
//
// - Original 'nds_color' code written by hunterk, modified by Pokefan531 and
// released into the public domain
//
// - Original 'natural_vision' code written by ShadX, modified by
// Hyllian and Sp00kyFox, released into the public domain
//
// 'Ported' (i.e. copy/paste) to DraStic format by jdgleaver
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// lcd1x+natural_vision differs from lcd3x in the following manner:
//
// > Omits LCD-style colour separation
//
// > Has 'correctly' aligned scanlines
//
// > Automatically supports 'high resolution 3d rendering' ON or OFF
//
// > Applies NDS colour correction followed by 'Natural Vision'
// colour enhancement
=============================================

<vertex>

attribute vec2 a_vertex_coordinate;
attribute vec2 a_texture_coordinate;
uniform vec4 u_texture_size;

varying vec2 v_texture_coordinate;

void main()
{
v_texture_coordinate = a_texture_coordinate;
gl_Position = vec4(a_vertex_coordinate.xy, 0.0, 1.0);
}

</vertex>

<fragment>

#ifndef BRIGHTEN_SCANLINES
#define BRIGHTEN_SCANLINES 16.0
#endif
#ifndef BRIGHTEN_LCD
#define BRIGHTEN_LCD 4.0
#endif
#ifndef NATVIS_GIN
#define NATVIS_GIN 1.91
#endif
#ifndef NATVIS_GOUT
#define NATVIS_GOUT 1.91
#endif
#ifndef NATVIS_Y
#define NATVIS_Y 1.1
#endif
#ifndef NATVIS_I
#define NATVIS_I 1.1
#endif
#ifndef NATVIS_Q
#define NATVIS_Q 1.1
#endif

#define PI 3.141592654

uniform sampler2D u_texture;
uniform vec4 u_texture_size;

varying vec2 v_texture_coordinate;

const float NDS_SCREEN_HEIGHT = 192.0;
const float INV_BRIGHTEN_SCANLINES_INC = 1.0 / (BRIGHTEN_SCANLINES + 1.0);
const float INV_BRIGHTEN_LCD_INC = 1.0 / (BRIGHTEN_LCD + 1.0);

// NDS Colour defines
#define NDS_LUM 0.89
#define NDS_R 0.87
#define NDS_G 0.645
#define NDS_B 0.73
#define NDS_RG 0.10
#define NDS_RB 0.10
#define NDS_GR 0.255
#define NDS_GB 0.17
#define NDS_BR -0.125
#define NDS_BG 0.255

const mat3 NDSColourMatrix = mat3(NDS_R, NDS_RG, NDS_RB,
NDS_GR, NDS_G, NDS_GB,
NDS_BR, NDS_BG, NDS_B);

// Natural Vision helpers
const mat3 RGBtoYIQ = mat3(0.299, 0.595716, 0.211456,
0.587, -0.274453, -0.522591,
0.114, -0.321263, 0.311135);

const mat3 YIQtoRGB = mat3(1.0, 1.0, 1.0,
0.95629572,-0.27212210,-1.10698902,
0.62102442,-0.64738060, 1.70461500);

const vec3 YIQ_lo = vec3(0.0, -0.595716, -0.522591);
const vec3 YIQ_hi = vec3(1.0, 0.595716, 0.522591);

void main()
{
// Note to self: uniform vec4 u_texture_size(1.0/w, 1.0/h, w, h)

// Generate LCD grid effect
// > Note the 0.25 pixel offset -> required to ensure that
// scanlines occur *between* pixels
// > Divide pixel coordinate by current scale factor (texture_height / NDS_SCREEN_HEIGHT)
vec2 angle = 2.0 * PI * (((v_texture_coordinate.xy * u_texture_size.zw) * NDS_SCREEN_HEIGHT * u_texture_size.y) - 0.25);

float yfactor = (BRIGHTEN_SCANLINES + sin(angle.y)) * INV_BRIGHTEN_SCANLINES_INC;
float xfactor = (BRIGHTEN_LCD + sin(angle.x)) * INV_BRIGHTEN_LCD_INC;

// Get colour sample and apply apply colour correction + enhancement
vec3 colour = pow(texture2D(u_texture, v_texture_coordinate.xy).rgb, vec3(NATVIS_GIN));
// > NDS colour
colour = clamp(colour * NDS_LUM, 0.0, 1.0);
colour = NDSColourMatrix * colour;
// > Natural vision
colour = RGBtoYIQ * colour;
colour = vec3(pow(colour.x, NATVIS_Y), colour.y * NATVIS_I, colour.z * NATVIS_Q);
colour = clamp(colour, YIQ_lo, YIQ_hi);
colour = YIQtoRGB * colour;
colour = pow(colour, vec3(1.0 / NATVIS_GOUT));

// Apply LCD grid effect
colour.rgb = yfactor * xfactor * colour.rgb;

gl_FragColor = vec4(colour.rgb, 1.0);
}

</fragment>
38 changes: 38 additions & 0 deletions sharp_bilinear+nds_color+natural_vision.dfx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// sharp_bilinear+nds_color+natural_vision shader
=============================================
<options>
name=Sharp Bilinear + NDS Color + Natural Vision
textures=1
</options>

<fheader>
#if GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
// Configuration
#define NATVIS_GIN 1.91 // "NaturalVision Gamma In"
// - default: 1.91, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_GOUT 1.91 // "NaturalVision Gamma Out"
// - default: 1.91, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_Y 1.1 // "NaturalVision Luminance"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_I 1.1 // "NaturalVision Orange-Cyan"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
#define NATVIS_Q 1.1 // "NaturalVision Magenta-Green"
// - default: 1.1, min: 0.0, max: 10.0, step: 0.01
</fheader>

<texture:0>
input=framebuffer
min_filter=GL_LINEAR
mag_filter=GL_LINEAR
</texture>

<pass>
shader=sharp_bilinear+nds_color+natural_vision.dsd
sampler:u_texture=0
</pass>
128 changes: 128 additions & 0 deletions sharp_bilinear+nds_color+natural_vision.dsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// sharp_bilinear+nds_color+natural_vision - This is an integer prescale
// filter that should be combined with bilinear hardware filtering (GL_LINEAR
// filter or some such) to achieve a smooth scaling result with minimum blur.
// This is good for pixel graphics that are scaled by non-integer factors. Also
// applies NDS colour correction followed by 'Natural Vision' colour enhancement
//
// - Original 'sharp_bilinear' code copyright (C) rsn8887 & TheMaister and
// released into the public domain
//
// - Original 'nds_color' code written by hunterk, modified by Pokefan531 and
// released into the public domain
//
// - Original 'natural_vision' code written by ShadX, modified by
// Hyllian and Sp00kyFox, released into the public domain
//
// 'Ported' (i.e. copy/paste) to DraStic format by jdgleaver
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
=============================================

<vertex>

attribute vec2 a_vertex_coordinate;
attribute vec2 a_texture_coordinate;

uniform vec4 u_texture_size;
uniform vec2 u_target_size;

varying vec2 precalc_texel;
varying vec2 precalc_scale;

void main()
{
gl_Position = vec4(a_vertex_coordinate.xy, 0.0, 1.0);

precalc_texel = a_texture_coordinate * u_texture_size.zw;
precalc_scale = floor(u_target_size.xy / u_texture_size.zw) + 1.0;
}

</vertex>

<fragment>

#ifndef NATVIS_GIN
#define NATVIS_GIN 1.91
#endif
#ifndef NATVIS_GOUT
#define NATVIS_GOUT 1.91
#endif
#ifndef NATVIS_Y
#define NATVIS_Y 1.1
#endif
#ifndef NATVIS_I
#define NATVIS_I 1.1
#endif
#ifndef NATVIS_Q
#define NATVIS_Q 1.1
#endif

uniform sampler2D u_texture;

uniform vec4 u_texture_size;
uniform vec2 u_target_size;

varying vec2 precalc_texel;
varying vec2 precalc_scale;

// NDS Colour defines
#define NDS_LUM 0.89
#define NDS_R 0.87
#define NDS_G 0.645
#define NDS_B 0.73
#define NDS_RG 0.10
#define NDS_RB 0.10
#define NDS_GR 0.255
#define NDS_GB 0.17
#define NDS_BR -0.125
#define NDS_BG 0.255

const mat3 NDSColourMatrix = mat3(NDS_R, NDS_RG, NDS_RB,
NDS_GR, NDS_G, NDS_GB,
NDS_BR, NDS_BG, NDS_B);

// Natural Vision helpers
const mat3 RGBtoYIQ = mat3(0.299, 0.595716, 0.211456,
0.587, -0.274453, -0.522591,
0.114, -0.321263, 0.311135);

const mat3 YIQtoRGB = mat3(1.0, 1.0, 1.0,
0.95629572,-0.27212210,-1.10698902,
0.62102442,-0.64738060, 1.70461500);

const vec3 YIQ_lo = vec3(0.0, -0.595716, -0.522591);
const vec3 YIQ_hi = vec3(1.0, 0.595716, 0.522591);

void main()
{
vec2 texel_floored = floor(precalc_texel);
vec2 s = fract(precalc_texel);
vec2 region_range = 0.5 - 0.5 / precalc_scale;

// Figure out where in the texel to sample to get correct pre-scaled bilinear.
// Uses the hardware bilinear interpolator to avoid having to sample 4 times manually.

vec2 center_dist = s - 0.5;
vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * precalc_scale + 0.5;

vec2 mod_texel = texel_floored + f;

// Get colour sample and apply colour correction + enhancement
vec3 colour = pow(texture2D(u_texture, mod_texel / u_texture_size.zw).rgb, vec3(NATVIS_GIN));
// > NDS colour
colour = clamp(colour * NDS_LUM, 0.0, 1.0);
colour = NDSColourMatrix * colour;
// > Natural vision
colour = RGBtoYIQ * colour;
colour = vec3(pow(colour.x, NATVIS_Y), colour.y * NATVIS_I, colour.z * NATVIS_Q);
colour = clamp(colour, YIQ_lo, YIQ_hi);
colour = YIQtoRGB * colour;
colour = pow(colour, vec3(1.0 / NATVIS_GOUT));

gl_FragColor = vec4(colour.rgb, 1.0);
}

</fragment>
Loading

0 comments on commit 4b477eb

Please sign in to comment.