基于Cocos2d-x学习OpenGL ES 2.0之多纹理
没想到原文出了那么多错别字,实在对不起观众了。介绍opengl es 2.0的不多。相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧。~~
子龙山人出了一个系列:基于Cocos2d-x学习OpenGL ES 2.0。弄c++来搞cocos2dx的可以看看。
教程是参考iphone的教程来写的,坑点也有不少,最主要的坑点还是在版本。所以还是弄个cocos2dx 3.2比较好。前两天辉辉说cocos2dx 3.2也很操蛋,.h里声明的返回值在源码实现的时候返回类型竟然变了。不得不吐槽一下~
子龙山人的教程只能教你照葫芦画瓢,什么原理的东西是压根就没涉及,有的还因为cocos2dx的封装过度会产生一些误导。
cocos2dx对opengl es封装的有点让人恶心,如果想学习opengl es是不建议在cocos2dx下进行学习的。
废话少说吧,开始正文。
根据子龙山人的教程,弄出了立方体纹理贴图,但是假如想在同一个面上贴多个纹理呢?该怎么实现?
本文提到两个方法,第一就是获取两个纹理,分别画图贴纹理,意思就是装顶点,装索引,绑定纹理,画图一。装顶点,装纹理,画图二。此时用到的都是GL_TEXTURE0,在frag文件中,只需要一个采样器就ok。
第二中方法就是用两个sampler,装顶点,装索引,绑定纹理一,绑定纹理二,画图。就OK了。
说起来比较简单,真要自己动手做,对于一个新手来说,过程还是有点小郁闷的。
下面就上源码了,对于步骤和方法的含义,此处不作介绍。相信强大的google和百度可以发挥巨大的作用。
第一种是立方体六个面贴上纹理,其中一个面再次贴上第二个纹理。
所用到的shader文件:
attribute vec4 a_position; //
attribute vec4 a_color; //
attribute vec2 TextureCoord; varying vec4 DestinationColor; //
varying vec2 v_texCoord; void main(void) { //
DestinationColor = a_color; //
v_texCoord = TextureCoord;
gl_Position = CC_MVPMatrix * a_position; //
}
myshader.vert
varying vec4 DestinationColor; //
varying vec2 v_texCoord; void main(void) { // gl_FragColor = DestinationColor * texture2D(CC_Texture0, v_texCoord) ; //
}
myshader.frag
所用到的两张图
头文件:
#ifndef _CubeTexture_H__
#define _CubeTexture_H__ #include "cocos2d.h" using namespace cocos2d; class CubeTexture : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated) override;
//we call our actual opengl commands here
void onDraw(); // implement the "static create()" method manually
CREATE_FUNC(CubeTexture); private:
Mat4 _modelViewMV;
CustomCommand _customCommand; GLProgram *mShaderProgram;
GLint _colorLocation;
GLint _positionLocation;
GLint _textureLocation; GLuint _textureUniform; GLuint _textureID;
GLuint _textureID2; GLuint vertexBuffer;
GLuint indexBuffer; GLuint _vertexBuffer2;
GLuint _indexBuffer2; }; #endif // __HELLOWORLD_SCENE_H__
CubeTexture.h
#include "CubeTexture.h"
using namespace GL; cocos2d::Scene* CubeTexture::createScene()
{
auto scene = Scene::create();
auto layer = CubeTexture::create();
scene->addChild(layer);
return scene;
} bool CubeTexture::init()
{
if ( Layer::init() )
{
mShaderProgram = new GLProgram;
mShaderProgram->initWithFilenames("myshader.vert","myshader.frag");
mShaderProgram->link();
mShaderProgram->updateUniforms(); _textureID = Director::getInstance()->getTextureCache()->addImage( "HelloWorld.png" )->getName();
_textureID2 = Director::getInstance()->getTextureCache()->addImage("item_powerup_fish.png")->getName();
glGenBuffers( , &vertexBuffer );
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer ); glGenBuffers( , &indexBuffer );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer ); return true;
}
return false;
} void CubeTexture::draw( Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated )
{
Layer::draw(renderer, transform, transformUpdated); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(CubeTexture::onDraw,this);
renderer->addCommand(&_customCommand);
} void CubeTexture::onDraw()
{
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); Mat4 modelViewMatrix;
Mat4::createLookAt(Vec3(,,), Vec3(,,), Vec3(,-,), &modelViewMatrix);
modelViewMatrix.translate(, , ); static float rotation = ;
modelViewMatrix.rotate(Vec3(,,),CC_DEGREES_TO_RADIANS(rotation)); Mat4 projectionMatrix;
Mat4::createPerspective(, /, 1.0, , &projectionMatrix);
Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, projectionMatrix);
Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix); typedef struct {
float Position[];
float Color[];
float TexCoord[];
} Vertex;
#define TEX_COORD_MAX 1 Vertex Vertices[] = {
// Front
{{, -, }, {, , , }, {TEX_COORD_MAX, }},
{{, , }, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{-, , }, {, , , }, {, TEX_COORD_MAX}},
{{-, -, }, {, , , }, {, }},
// Back
{{, , -}, {, , , }, {TEX_COORD_MAX, }},
{{-, -, -}, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{, -, -}, {, , , }, {, TEX_COORD_MAX}},
{{-, , -}, {, , , }, {, }},
// Left
{{-, -, }, {, , , }, {TEX_COORD_MAX, }},
{{-, , }, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{-, , -}, {, , , }, {, TEX_COORD_MAX}},
{{-, -, -}, {, , , }, {, }},
// Right
{{, -, -}, {, , , }, {TEX_COORD_MAX, }},
{{, , -}, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{, , }, {, , , }, {, TEX_COORD_MAX}},
{{, -, }, {, , , }, {, }},
// Top
{{, , }, {, , , }, {TEX_COORD_MAX, }},
{{, , -}, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{-, , -}, {, , , }, {, TEX_COORD_MAX}},
{{-, , }, {, , , }, {, }},
// Bottom
{{, -, -}, {, , , }, {TEX_COORD_MAX, }},
{{, -, }, {, , , }, {TEX_COORD_MAX, TEX_COORD_MAX}},
{{-, -, }, {, , , }, {, TEX_COORD_MAX}},
{{-, -, -}, {, , , }, {, }}
};
int vertexCount = sizeof(Vertices) / sizeof(Vertices[]); GLubyte Indices[] = {
// Front
, , ,
, , ,
// Back
, , ,
, , ,
// Left
, , ,
, , ,
// Right
, , ,
, , ,
// Top
, , ,
, , ,
// Bottom
, , ,
, ,
}; // 1) Add to top of file
const Vertex Vertices2[] = {
{{0.5, -0.5, 0.01}, {, , , }, {, }},
{{0.5, 0.5, 0.01}, {, , , }, {, }},
{{-0.5, 0.5, 0.01}, {, , , }, {, }},
{{-0.5, -0.5, 0.01}, {, , , }, {, }},
}; const GLubyte Indices2[] = {
, , ,
}; glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices),Indices,GL_STATIC_DRAW); _positionLocation = glGetAttribLocation(mShaderProgram->getProgram(), "a_position");
_colorLocation = glGetAttribLocation(mShaderProgram->getProgram(), "a_color"); _textureLocation = glGetAttribLocation(mShaderProgram->getProgram(), "TextureCoord");
_textureUniform = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0"); mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); glEnableVertexAttribArray(_positionLocation);
glEnableVertexAttribArray(_colorLocation);
glEnableVertexAttribArray(_textureLocation); glVertexAttribPointer(_positionLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Position)); glVertexAttribPointer(_colorLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex),(GLvoid*)offsetof(Vertex, Color)); glVertexAttribPointer(_textureLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex),
(GLvoid*)offsetof(Vertex, TexCoord));
//
////set sampler
GL::bindTexture2DN(, _textureID);
//glActiveTexture( GL_TEXTURE0 );
//glBindTexture(GL_TEXTURE_2D, _textureID);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDrawElements(GL_TRIANGLES, , GL_UNSIGNED_BYTE, );
glUniform1i(_textureUniform, ); // unnecc in practice glGenBuffers(, &_vertexBuffer2);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW); glGenBuffers(, &_indexBuffer2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer2);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices2), Indices2, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer2); GL::bindTexture2DN(, _textureID2);
glUniform1i(_textureUniform, ); // unnecc in practice glVertexAttribPointer(_positionLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex), );
glVertexAttribPointer(_colorLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * ));
glVertexAttribPointer(_textureLocation, , GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * )); glDrawElements(GL_TRIANGLE_STRIP, sizeof(Indices2)/sizeof(Indices2[]), GL_UNSIGNED_BYTE, ); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,vertexCount); CHECK_GL_ERROR_DEBUG();
glDisable(GL_DEPTH_TEST); Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
CubeTexture
运行结果:
方法二,所需要的shader文件:
attribute vec4 a_position;
attribute vec2 a_texCoord; varying vec2 v_texCoord; void main(void) {
gl_Position = CC_MVPMatrix * a_position;
v_texCoord = a_texCoord;
}
multiTexture.vert
precision mediump float;
varying vec2 v_texCoord;
//uniform sampler2D s_lightMap;
//uniform sampler2D s_baseMap; void main(void) {
vec4 baseColor;
vec4 lightColor;
//baseColor = texture2D( s_baseMap, v_texCoord);
//lightColor = texture2D( s_lightMap, v_texCoord );
baseColor = texture2D( CC_Texture0, v_texCoord);
lightColor = texture2D( CC_Texture1, v_texCoord );
gl_FragColor = baseColor * ( lightColor + 0.25 );
}
multiTexture
所需要的图
头文件
#ifndef _MultiTexture_H__
#define _MultiTexture_H__ #include "cocos2d.h" using namespace cocos2d; class MultiTexture : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated) override;
//we call our actual opengl commands here
void onDraw(); // implement the "static create()" method manually
CREATE_FUNC(MultiTexture); private:
Mat4 _modelViewMV;
CustomCommand _customCommand; GLProgram *mShaderProgram;
// attribute locations
GLint _positionLoc;
GLint _texCoordLoc; // sampler locations
GLuint _baseMapLoc;
GLuint _lightMapLoc;
// Texture handle
GLuint _baseMapTexId;
GLuint _lightMapTexId; GLuint VAO;
GLuint vertexBuffer;
GLuint indexBuffer; }; #endif // __HELLOWORLD_SCENE_H__
MultiTexture.h
源文件
#include "MultiTexture.h" cocos2d::Scene* MultiTexture::createScene()
{
auto scene = Scene::create();
auto layer = MultiTexture::create();
scene->addChild(layer);
return scene;
} bool MultiTexture::init()
{
if ( Layer::init() )
{
mShaderProgram = new GLProgram;
mShaderProgram->initWithFilenames("multiTexture.vert","multiTexture.frag");
mShaderProgram->link();
mShaderProgram->updateUniforms(); _baseMapTexId = Director::getInstance()->getTextureCache()->addImage( "HelloWorld.png" )->getName();
_lightMapTexId = Director::getInstance()->getTextureCache()->addImage("crate.jpg")->getName();
glGenVertexArrays(, &VAO);
glBindVertexArray(VAO); glGenBuffers( , &vertexBuffer );
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer ); glGenBuffers( , &indexBuffer );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer ); return true;
}
return false;
} void MultiTexture::draw( Renderer *renderer, const Mat4 &transform, uint32_t transformUpdated )
{
Layer::draw(renderer, transform, transformUpdated); _customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(MultiTexture::onDraw,this);
renderer->addCommand(&_customCommand);
} void MultiTexture::onDraw()
{
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); typedef struct {
float Position[];
float TexCoord[];
} Vertex;
#define TEX_COORD_MAX 1 Vertex Vertices[] = { {{-0.5, 0.5, }, {, }},
{{-0.5, -0.5, }, {, TEX_COORD_MAX}},
{{0.5, -0.5, }, { TEX_COORD_MAX,TEX_COORD_MAX}},
{{0.5, 0.5, }, {TEX_COORD_MAX, }}, };
int vertexCount = sizeof(Vertices) / sizeof(Vertices[]); GLubyte Indices[] = {
, , ,
, , ,
}; glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices),Indices,GL_STATIC_DRAW); _positionLoc = glGetAttribLocation(mShaderProgram->getProgram(), "a_position");
_texCoordLoc = glGetAttribLocation(mShaderProgram->getProgram(), "a_texCoord");
//_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_baseMap");
//_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_lightMap");
_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0");
_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture1"); glEnableVertexAttribArray(_positionLoc);
glEnableVertexAttribArray(_texCoordLoc); glVertexAttribPointer(_positionLoc, , GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Position));
glVertexAttribPointer(_texCoordLoc, , GL_FLOAT, GL_FALSE, sizeof(Vertex),
(GLvoid*)offsetof(Vertex, TexCoord)); mShaderProgram->use();
mShaderProgram->setUniformsForBuiltins(); glEnable(GL_DEPTH_TEST);
glBindVertexArray(VAO); GL::bindTexture2DN(, _lightMapTexId);
glUniform1i(_lightMapLoc, ); // unnecc in practice GL::bindTexture2DN(, _baseMapTexId);
glUniform1i(_baseMapLoc, ); // unnecc in practice glDrawElements(GL_TRIANGLES,, GL_UNSIGNED_BYTE, ); glBindVertexArray();
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(,); CHECK_GL_ERROR_DEBUG();
glDisable(GL_DEPTH_TEST); Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
MultiTexture
运行效果:
第二种方法中,
cpp内的:
//_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_baseMap");
//_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "s_lightMap");
_baseMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture0");
_lightMapLoc = glGetUniformLocation(mShaderProgram->getProgram(), "CC_Texture1");
和shader内的
//baseColor = texture2D( s_baseMap, v_texCoord);
//lightColor = texture2D( s_lightMap, v_texCoord );
baseColor = texture2D( CC_Texture0, v_texCoord);
lightColor = texture2D( CC_Texture1, v_texCoord );
将注释解开,把下面两行注掉。同样可以。这说明了,cocos2dx在进行编译shader的时候内置了多个uniform值。大家可以看一下,其中就包括CC_Texture0系列。
其实用起来不算方便了,而不注意的人,可能会声明和内置变量相同的名字,此时,咳咳咳咳咳~ shader编译的时候就会出错了。不知道为啥cocos2dx要多次一举。
还有一点:
////set sampler
GL::bindTexture2DN(0, _textureID);
//glActiveTexture( GL_TEXTURE0 );
//glBindTexture(GL_TEXTURE_2D, _textureID);
我使用了GL::bindTexture2DN 方法,而并没有使用opengl es原装的 glActiveTexture 和glBindTexture这两个方法。其实GL::bindTexture2DN 内部就调用了后面的两个方法,那为何不直接用后面的两个方法呢?
原因是,直接用opengl es的方法,会出错!!!尼玛 这才是坑点。跟踪后发现,cocos2dx给GL相关的东西添加了一个StateCache的东西,当activeTexture时,需要更改cache内的东西。直接调用glActiveTexture的方法,就略去了往cache内塞东西的步骤,这样就出错了。
猜测是cocos2dx进行渲染的时候,调用了cache内的什么东西。尼玛,你还能封装的再恶心一点么?
所以说,不喜欢cocos2dx这种处理问题的方法的,可以完全抛开cocos2dx了。
基于Cocos2d-x学习OpenGL ES 2.0之多纹理的更多相关文章
- 基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)
在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-P ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)
在上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了.在这篇文章中,我们不再画三角形了,改为画四边形.下篇教程,我们就可以画立方体了, ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)
前言 在本系列教程中,我会以当下最流行的2D引擎Cocos2d-x为基础,介绍OpenGL ES 2.0的一些基本用法.本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2d-x过程中,知其然 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)
Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)
在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时, ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)
在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerCol ...
- OpenGL ES 3.0之Texturing纹理详解(一)
本文流程 1.Texturing基础 2.装载Texturing和mipmapping 3.纹理过滤和包装 4.Texture level-of-detail, swizzles, and depth ...
- OpenGL ES 3.0之Texturing纹理详解(二)
Texture Filtering and Mipmapping 纹理过滤与多级纹理 前面我们已经讲了单个2D图像的2D纹理的介绍,这篇文章主要讲解多级纹理.纹理坐标是用于生成一个2D索引,当放大和缩 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)
在上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率. 本教程将带领大家一起走进3D--绘制一个立方体.其实画立方体本质上和画三角形没什么区别,所有的 ...
随机推荐
- UDP和TCP的比較
当client须要请求数据库server上的某些数据时,它至少须要三个数据报来建立TCP连接.三个数据报礼发送和确认少量数据,三个用来关闭连接. 然而,假设使用UDP的话,只须要发出两个数据报就能达到 ...
- VB 中定义FileSystemObject对象,要先添加对象
存取文件的方法有很多种,可以使用上述VB提供的函数,使用Windows API函数等等,但是最简单的方法是使用FileSystemObject对象. 1.使用FileSystemObject对象 F ...
- PHP $_POST
$_POST 变量用于收集来自 method="post" 的表单中的值. $_POST 变量 $_POST 变量是一个数组,内容是由 HTTP POST 方法发送的变量名称和值. ...
- Ubuntu系统安装VMware Tools的简单方法
不少网友反映在VMWare虚拟机下安装Ubuntu系统后无法安装VMware Tools,这里给出一个简单方法,只需要几步即可解决. 第一步:进入系统后,点击虚拟机上的安装vmware tools,回 ...
- spring mvc异常的处理
1.全局处理 <!-- 总错误处理 --> <bean id="exceptionResolver" class="org.springframewor ...
- 使用quartz进行容器启动时登陆接口服务器和接口服务器进行心跳连接
1.下载quartz的相应jar包 2.增加spring配置文件(applicationContext-quartz.xml) 内容如下: <?xml version="1.0&quo ...
- servlet 多线程
servlet在服务器中只有一个实例,那么它响应请求的方式应该是多线程. 一,servlet容器如何同时处理多个请求. Servlet采用多线程来处理多个请求同时访问,Servelet容器维护了一个线 ...
- AWK中的OFS的问题
echo a b c d |awk '{OFS = ":";print $0}' 我的理解是应该把输出显示为如下的方式 a:b:c:d dan但执行的结果不是这样的 a b c d ...
- 利用Aspose.BarCode生成条码
生成条码有很多控件,大部分好的控件,做出来的条码精确清晰,但是往往该部分的控件费用都很高,这里推荐大家使用6.0版本的破解版,可以生成无水印,下方也可以不显示文字. 1.下图是 onbarcode 控 ...
- 【LeetCode】136. Single Number (4 solutions)
Single Number Given an array of integers, every element appears twice except for one. Find that sing ...