import { BaseRenderer } from "./BaseRenderer";
import { Utils } from "../core/Utils";
import { BlendMode } from "../rendering/BlendMode";
import {
BASE_VERTEX_SHADER,
BASE_VERTEX_SHADER_INITIALIZATION,
BASE_VERTEX_SHADER_POSITION,
} from "../utils/baseVertexShaderUtils";
/**
* @typedef {Object} NormalMapRendererConfig
* @extends {RendererConfig}
* @property {TextureInfo} heightMap
*/
/**
* <pre>
* Normal map renderer
* - Renders a normal map from height map texture
* </pre>
* @extends {BaseRenderer}
* @property {TextureInfo} heightMap
*/
export class NormalMapRenderer extends BaseRenderer {
/**
* Creates an instance of NormalMapRenderer.
* @constructor
* @param {NormalMapRendererConfig} config
*/
constructor(config = {}) {
config = Utils.initRendererConfig(config);
// prettier-ignore
Utils.setLocations(config, [
"uF"
]);
super(config);
this.heightMap = config.heightMap;
}
/**
* @ignore
*/
$render() {
const locations = this.$locations;
this.context.setBlendMode(BlendMode.NORMAL);
this.$useTextureAt(this.heightMap, locations.uB, 0);
this.$gl.uniform2f(locations.uF, this.width, this.height);
this.$uploadBuffers();
this.$drawInstanced(1);
}
// prettier-ignore
/**
* @returns {string}
* @ignore
*/
$createVertexShader() {
return BASE_VERTEX_SHADER_INITIALIZATION +
"out vec2 " +
"v0;" +
"void main(void){" +
BASE_VERTEX_SHADER +
"v0=" + BASE_VERTEX_SHADER_POSITION + ";" +
"}";
}
// prettier-ignore
/**
* @returns {string}
* @ignore
*/
$createFragmentShader() {
return Utils.GLSL.DEFINE.Z +
Utils.GLSL.DEFINE.HEIGHT +
"in vec2 " +
"v0;" +
"uniform vec2 " +
"uF;" +
"uniform sampler2D " +
"uB;" +
"out vec4 " +
"oCl;" +
"void main(void){" +
"vec2 " +
"ts=floor(uF)," +
"p=1./ts," +
"p0=floor(v0.xy*ts);" +
"float " +
"h0=texture(uB,p0*p).g," +
"h1=texture(uB,(p0+Z.yx)*p).g," +
"h2=texture(uB,(p0+Z.xy)*p).g;" +
"vec3 " +
"nm=normalize(" +
"cross(" +
"vec3(1,0,h1-h0)," +
"vec3(0,1,h2-h0)" +
"))*HEIGHT*Z.yzy;" +
"oCl=vec4(nm*.5+.5,1);" +
"}";
}
}