Shark.cpp
branchv_0
changeset 28 4cbd9c0beb4c
parent 27 2a156cb51479
child 30 e15d04d98fca
equal deleted inserted replaced
27:2a156cb51479 28:4cbd9c0beb4c
    16  */
    16  */
    17 
    17 
    18 #include <iostream>
    18 #include <iostream>
    19 #include <iomanip>
    19 #include <iomanip>
    20 #include <string>
    20 #include <string>
       
    21 #include <charconv>
    21 #include <memory>
    22 #include <memory>
    22 #include <functional>
    23 #include <functional>
    23 #include <sstream>
    24 #include <sstream>
    24 #include <vector>
    25 #include <vector>
    25 
    26 
    48 
    49 
    49 		GLint uModel = -2;
    50 		GLint uModel = -2;
    50 		GLint uView = -2;
    51 		GLint uView = -2;
    51 		GLint uProjection = -2;
    52 		GLint uProjection = -2;
    52 		GLint uTexture = -2;
    53 		GLint uTexture = -2;
       
    54 		GLint uTextureScale = -2;
    53 	} ProgAttr;
    55 	} ProgAttr;
    54 
    56 
    55 	struct {
    57 	struct {
    56 		float yaw = -90.f;
    58 		float yaw = -90.f;
    57 		float pitch = 0.f;
    59 		float pitch = 0.f;
   183 	int setNonBlocking(int fd);
   185 	int setNonBlocking(int fd);
   184 	void loadVertices();
   186 	void loadVertices();
   185 	void parametrizeTexture(std::shared_ptr<Texture> tex);
   187 	void parametrizeTexture(std::shared_ptr<Texture> tex);
   186 	bool reloadTexture(const std::string& fileName);
   188 	bool reloadTexture(const std::string& fileName);
   187 	void loadTextures();
   189 	void loadTextures();
   188 	std::shared_ptr<Program> loadShaders();
   190 	void loadShaders();
       
   191 	void updateVariableLocations();
   189 	bool reloadShader(const std::string& fileName);
   192 	bool reloadShader(const std::string& fileName);
   190 	void setTitle(const std::string& suffix = "");
   193 	void setTitle(const std::string& suffix = "");
   191 	static const std::string getDefaultFile(const std::string& relativePath);
   194 	static const std::string getDefaultFile(const std::string& relativePath);
   192 
   195 
   193 };
   196 };
   267 	clear();
   270 	clear();
   268 	glXSwapBuffers(dpy, win);
   271 	glXSwapBuffers(dpy, win);
   269 
   272 
   270 
   273 
   271 	// Load GLSL shaders:
   274 	// Load GLSL shaders:
   272 	shaderProgram = loadShaders();
   275 	loadShaders();
   273 	loadTextures();
   276 	loadTextures();
   274 	loadVertices();
   277 	loadVertices();
   275 
   278 
   276 	auto toggleFullscreen = [&]() {
   279 	auto toggleFullscreen = [&]() {
   277 		full = setFullscreen(dpy, win, !full);
   280 		full = setFullscreen(dpy, win, !full);
   466 	// glBindVertexArray(vao);
   469 	// glBindVertexArray(vao);
   467 
   470 
   468 	glm::mat4 model = glm::mat4(1.0f); // identity matrix
   471 	glm::mat4 model = glm::mat4(1.0f); // identity matrix
   469 	glUniformMatrix4fv(ProgAttr.uModel, 1, GL_FALSE, &model[0][0]);
   472 	glUniformMatrix4fv(ProgAttr.uModel, 1, GL_FALSE, &model[0][0]);
   470 
   473 
       
   474 	// TODO: draw a rectangle for each texture
       
   475 	glUniform1f(ProgAttr.uTextureScale, textures[0]->getScale());
       
   476 
   471 	glDrawArrays(GL_TRIANGLES, 0, 2 * 3); // see loadVertices()
   477 	glDrawArrays(GL_TRIANGLES, 0, 2 * 3); // see loadVertices()
   472 	std::cerr << "GLSL: glDrawArrays()" << std::endl;
   478 	std::cerr << "GLSL: glDrawArrays()" << std::endl;
   473 }
   479 }
   474 
   480 
   475 void Shark::Impl::log(LogLevel level, std::string message) {
   481 void Shark::Impl::log(LogLevel level, std::string message) {
   544 
   550 
   545 void Shark::Impl::parametrizeTexture(std::shared_ptr<Texture> tex) {
   551 void Shark::Impl::parametrizeTexture(std::shared_ptr<Texture> tex) {
   546 	XAttrs xa(tex->getFileName());
   552 	XAttrs xa(tex->getFileName());
   547 	std::string magf = xa["shader-shark.texture.mag-filter"];
   553 	std::string magf = xa["shader-shark.texture.mag-filter"];
   548 	std::string minf = xa["shader-shark.texture.min-filter"];
   554 	std::string minf = xa["shader-shark.texture.min-filter"];
   549 	// TODO: std::string scale = xa["shader-shark.texture.scale"];
   555 	std::string scale = xa["shader-shark.texture.scale"];
   550 	// TODO: keep MappedFile locked until we read the attributes
       
   551 
   556 
   552 	auto GLT2D = GL_TEXTURE_2D;
   557 	auto GLT2D = GL_TEXTURE_2D;
   553 	auto MAG = GL_TEXTURE_MAG_FILTER;
   558 	auto MAG = GL_TEXTURE_MAG_FILTER;
   554 	auto MIN = GL_TEXTURE_MIN_FILTER;
   559 	auto MIN = GL_TEXTURE_MIN_FILTER;
   555 
   560 
   556 	if (magf == "linear") glTexParameteri(GLT2D, MAG, GL_LINEAR);
   561 	if (magf == "linear") glTexParameteri(GLT2D, MAG, GL_LINEAR);
   557 	else if (magf == "nearest") glTexParameteri(GLT2D, MAG, GL_NEAREST);
   562 	else if (magf == "nearest") glTexParameteri(GLT2D, MAG, GL_NEAREST);
   558 
   563 
   559 	if (minf == "linear") glTexParameteri(GLT2D, MIN, GL_LINEAR);
   564 	if (minf == "linear") glTexParameteri(GLT2D, MIN, GL_LINEAR);
   560 	else if (minf == "nearest") glTexParameteri(GLT2D, MIN, GL_NEAREST);
   565 	else if (minf == "nearest") glTexParameteri(GLT2D, MIN, GL_NEAREST);
       
   566 
       
   567 	if (scale.size()) {
       
   568 		float sc;
       
   569 		if (std::from_chars(scale.data(), scale.data() + scale.size(), sc).ec
       
   570 				== std::errc{}) tex->setScale(sc);
       
   571 		else std::cerr << "Invalid texture scale value - expecting float\n";
       
   572 		// tex->setScale(std::stof(scale)); // locale-dependent (. vs ,)
       
   573 	}
   561 }
   574 }
   562 
   575 
   563 void Shark::Impl::loadTextures() {
   576 void Shark::Impl::loadTextures() {
   564 	// Load default texture if there is no configured:
   577 	// Load default texture if there is no configured:
   565 	if (cfg.textures.empty())
   578 	if (cfg.textures.empty())
   593 		}
   606 		}
   594 	}
   607 	}
   595 	return false;
   608 	return false;
   596 }
   609 }
   597 
   610 
   598 std::shared_ptr<Program> Shark::Impl::loadShaders() {
   611 void Shark::Impl::loadShaders() {
   599 	try {
   612 	// Vertex Array Object (VAO)
   600 		// Vertex Array Object (VAO)
   613 	GLuint vao;
   601 		GLuint vao;
   614 	glGenVertexArrays(1, &vao);
   602 		glGenVertexArrays(1, &vao);
   615 	glBindVertexArray(vao);
   603 		glBindVertexArray(vao);
   616 	// VAO - something like context for bound data/variables
   604 		// VAO - something like context for bound data/variables
   617 	// We can switch multiple VAOs. VAO can contain multiple VBOs.
   605 		// We can switch multiple VAOs. VAO can contain multiple VBOs.
   618 	// what-are-vertex-array-objects
   606 		// what-are-vertex-array-objects
   619 
   607 
   620 	// Vertex Buffer Object (VBO):
   608 		// Vertex Buffer Object (VBO):
   621 	GLuint vbo;
   609 		GLuint vbo;
   622 	glGenBuffers(1, &vbo);
   610 		glGenBuffers(1, &vbo);
   623 	glBindBuffer(GL_ARRAY_BUFFER, vbo);
   611 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
   624 
   612 
   625 	{
   613 		{
   626 		// Load default shaders if there are no configured:
   614 			// Load default shaders if there are no configured:
   627 		int vc = 0;
   615 			int vc = 0;
   628 		int fc = 0;
   616 			int fc = 0;
   629 		auto& ss = cfg.shaders;
   617 			auto& ss = cfg.shaders;
   630 		for (const auto& s : ss) if (s.type == "vertex") vc++;
   618 			for (const auto& s : ss) if (s.type == "vertex") vc++;
   631 		for (const auto& s : ss) if (s.type == "fragment") fc++;
   619 			for (const auto& s : ss) if (s.type == "fragment") fc++;
   632 		auto& d = getDefaultFile;
   620 			auto& d = getDefaultFile;
   633 		if (vc == 0) ss.push_back({d("shaders/default.vert"), "vertex"});
   621 			if (vc == 0) ss.push_back({d("shaders/default.vert"), "vertex"});
   634 		if (fc == 0) ss.push_back({d("shaders/default.frag"), "fragment"});
   622 			if (fc == 0) ss.push_back({d("shaders/default.frag"), "fragment"});
   635 	}
   623 		}
   636 
   624 
   637 	shaderProgram = std::make_shared<Program>();
   625 		std::shared_ptr<Program> program = std::make_shared<Program>();
   638 
   626 
   639 	// glBindFragDataLocation(program, 0, "outColor");
   627 		// glBindFragDataLocation(program, 0, "outColor");
   640 	// glBindAttribLocation(program, LOC.input, "vertices");
   628 		// glBindAttribLocation(program, LOC.input, "vertices");
   641 
   629 
   642 	for (const Configuration::Shader definition : cfg.shaders) {
   630 		for (const Configuration::Shader definition : cfg.shaders) {
   643 		Shader::Type type;
   631 			Shader::Type type;
   644 		std::string fileName = definition.fileName;
   632 			std::string fileName = definition.fileName;
   645 		if (definition.type == "fragment") type = Shader::Type::FRAGMENT;
   633 			if (definition.type == "fragment") type = Shader::Type::FRAGMENT;
   646 		else if (definition.type == "vertex") type = Shader::Type::VERTEX;
   634 			else if (definition.type == "vertex") type = Shader::Type::VERTEX;
   647 		else throw std::invalid_argument("unsupported shader type");
   635 			else throw std::invalid_argument("unsupported shader type");
   648 
   636 
   649 		MappedFile file(fileName);
   637 			MappedFile file(fileName);
   650 		std::shared_ptr<Shader> shader = std::make_shared<Shader>(
   638 			std::shared_ptr<Shader> shader = std::make_shared<Shader>(
   651 				type, file, fileName);
   639 					type, file, fileName);
   652 
   640 
   653 		shaderProgram->attachShader(*shader.get());
   641 			program->attachShader(*shader.get());
   654 		shaders.push_back(shader);
   642 			shaders.push_back(shader);
   655 		watchedFiles.push_back(fileMonitor.watch(fileName));
   643 			watchedFiles.push_back(fileMonitor.watch(fileName));
   656 		std::cerr << "GLSL loaded: " << fileName.c_str() << std::endl;
   644 			std::cerr << "GLSL loaded: " << fileName.c_str() << std::endl;
   657 		// We may detach and delete shaders,
   645 			// We may detach and delete shaders,
   658 		// but our shaders are small, so we keep them for later reloading.
   646 			// but our shaders are small, so we keep them for later reloading.
   659 	}
   647 		}
   660 
   648 
   661 	shaderProgram->link();
   649 		// GLSL compiler does very efficient / aggressive optimization.
   662 	updateVariableLocations();
   650 		// Attributes and uniforms that are not used in the shader are deleted.
   663 	// listVariables(program);
   651 		// And even if we e.g. read color from a texture and overwrite it,
   664 	std::cerr << "GLSL shader count: " << shaders.size() << std::endl;
   652 		// the variable is still deleted and considered „inactive“.
   665 }
   653 		// Functions glGetAttribLocation() and glGetUniformLocation() return -1.
   666 
   654 
   667 void Shark::Impl::updateVariableLocations() {
   655 		program->link();
   668 	// GLSL compiler does very efficient / aggressive optimization.
   656 
   669 	// Attributes and uniforms that are not used in the shader are deleted.
   657 		ProgAttr.aVertexXYZ = program->getAttribLocation("aVertexXYZ");
   670 	// And even if we e.g. read color from a texture and overwrite it,
   658 		ProgAttr.aTextureXY = program->getAttribLocation("aTextureXY");
   671 	// the variable is still deleted and considered „inactive“.
   659 		ProgAttr.uModel = program->getUniformLocation("uModel");
   672 	// Functions glGetAttribLocation() and glGetUniformLocation() return -1.
   660 		ProgAttr.uView = program->getUniformLocation("uView");
   673 	ProgAttr.aVertexXYZ = shaderProgram->getAttribLocation("aVertexXYZ");
   661 		ProgAttr.uProjection = program->getUniformLocation("uProjection");
   674 	ProgAttr.aTextureXY = shaderProgram->getAttribLocation("aTextureXY");
   662 		ProgAttr.uTexture = program->getUniformLocation("uTexture");
   675 	ProgAttr.uModel = shaderProgram->getUniformLocation("uModel");
   663 		ProgAttr.fColor = program->getFragDataLocation("fColor");
   676 	ProgAttr.uView = shaderProgram->getUniformLocation("uView");
   664 		program->bindFragDataLocation("fColor", ProgAttr.fColor);
   677 	ProgAttr.uProjection = shaderProgram->getUniformLocation("uProjection");
   665 		// listVariables(program);
   678 	ProgAttr.uTexture = shaderProgram->getUniformLocation("uTexture");
   666 		std::cerr << "GLSL shader count: " << shaders.size() << std::endl;
   679 	ProgAttr.uTextureScale = shaderProgram->getUniformLocation("uTextureScale");
   667 		return program;
   680 	ProgAttr.fColor = shaderProgram->getFragDataLocation("fColor");
   668 	} catch (const std::exception& e) {
   681 	shaderProgram->bindFragDataLocation("fColor", ProgAttr.fColor);
   669 		std::cerr << "Error while loading shaders: " << e.what() << std::endl;
       
   670 	} catch (...) {
       
   671 		std::cerr << "Error while loading shaders: unknown" << std::endl;
       
   672 	}
       
   673 	throw std::logic_error("GLSL: loadShaders() failed");
       
   674 }
   682 }
   675 
   683 
   676 bool Shark::Impl::reloadShader(const std::string& fileName) {
   684 bool Shark::Impl::reloadShader(const std::string& fileName) {
   677 	for (auto shader : shaders) {
   685 	for (auto shader : shaders) {
   678 		if (shader->getFileName() == fileName) {
   686 		if (shader->getFileName() == fileName) {
   679 			shader->update(MappedFile(fileName));
   687 			shader->update(MappedFile(fileName));
   680 			shaderProgram->link();
   688 			shaderProgram->link();
       
   689 			updateVariableLocations();
   681 			return true;
   690 			return true;
   682 		}
   691 		}
   683 	}
   692 	}
   684 	return false;
   693 	return false;
   685 }
   694 }